Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I combine BiPredicate and Predicate?

I have two lambda functions (predicates):

final Predicate<Node> isElement = node -> node.getNodeType() == Node.ELEMENT_NODE;
final BiPredicate<Node, String> hasName = (node, name) -> node.getNodeName().equals(name);

Which I want to combine in some concise way, something like this:

// Pseudocode
isElement.and(hasName("tag")) // type of Predicate

and then pass to another lambda function:

final BiFunction<Node, Predicate<Node>, List<Node>> getChilds = (node, cond) -> {
    List<Node> resultList = new ArrayList<>();
    NodeList nodeList = node.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); ++i) {
        Node tmp = nodeList.item(i);
        if (cond.test(tmp)) {
            resultList.add(tmp);
        }
    }
    return resultList;
};

As a result I'm expecting it would look like the following:

List<Node> listNode = getChilds.apply(document, isElement.and(hasName("tag")));

But and method of Predicate doesn't accept BiPredicate parameter.

How I could do this?

like image 579
likern Avatar asked Jun 12 '15 08:06

likern


People also ask

What is the difference between predicate and bipredicate in Java?

A Predicate<T> interface defined in java.util.function package. It represents a boolean-valued function with one argument. It is kind of a functional interface whose functional method is the test (). BiPredicate<T, U> interface is similar to the Predicate<T> interface with two arguments.

How to use predicates in real life?

For example, we can use predicates in these real-life usecases: and so on… 1.2. Using Predicate with Stream As we know, Predicate is a functional interface that means we can pass it in lambda expressions wherever a predicate is expected. For example, one such method is filter () method from Stream interface.

How do you combine multiple predicates in SQL?

We can also combine more than one predicate to make a predicate chain or complex predicate, as we do in builder pattern. So, in this function, we pass the list of employees and we pass a predicate, then this function will return a new collection of employees satisfying the condition mentioned in parameter predicate.

What is bipredicate<T> interface in Python?

It represents a boolean-valued function with one argument. It is kind of a functional interface whose functional method is the test (). BiPredicate<T, U> interface is similar to the Predicate<T> interface with two arguments. It can be used as an assignment target for a lambda expression.


1 Answers

Stop rewriting every method into a lambda expression. There is no real benefit. If you have an ordinary method, you can call it by its simple name without having to append apply, test or similar. If you really need a function then, you can still create a static method reference using the :: operator.

So if you want to improve you code, think about using the new API instead of overusing the Java language features. For example:

static List<Node> getChilds(Node node, Predicate<Node> cond) {
    NodeList nodeList = node.getChildNodes();
    return IntStream.range(0, nodeList.getLength()).mapToObj(nodeList::item)
                    .filter(cond).collect(Collectors.toList());
}

Regarding you attempt to combine Predicates. Of course, you can express everything as a function without compromise. For example:

Predicate<Node> isElement = node -> node.getNodeType() == Node.ELEMENT_NODE;
Function<Node, String> nodeName = Node::getNodeName;
Predicate<Node> both = isElement.and(nodeName.andThen("tag"::equals)::apply);

but is this really an improvement?

You may simply write

Predicate<Node> both = isElement.and(n -> n.getNodeName().equals("tag"));

or, even simpler, since Nodes not representing ELEMENT nodes will never report a node name of "tag" you don't need the first predicate at all and the entire operation becomes:

getChilds(document, n -> "tag".equals(n.getNodeName()));

That might not feel as fancy as complicated function composition, but it's a practical solution.

like image 190
Holger Avatar answered Nov 08 '22 21:11

Holger