How to 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);

What I want to combine in short form is something like this:

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

and then move on 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 expect it to look like this:

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

But the method and Predicatedoes not accept the parameter BiPredicate.

How could I do this?

+4
source share
3 answers

Stop overwriting each method in a lambda expression. There is no real benefit. If you have a regular method, you can call it a simple name without adding apply, testor similar. If you really need a function, you can still create a method reference using the operator ::.

, , API Java. :

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());
}

Predicate s. , . .

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);

?

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

, , Node ELEMENT node "tag", , :

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

, , .

+5

, curries BiPredicate , .and() .

isElement.and(curryRight(hasName, "tag"))

:

isElement.and(node -> hasName.test(node, "tag"))

+4

lambada hasName hasName(String name), -.

final Predicate<Node> hasName(String name) { return node -> node.getNodeName().equals(name); }

Then your code will work.

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

All Articles