lap*_*nis 3 java predicate java-stream
我google了很多,但没有找到答案.这是我有的:
parentList.forEach(p -> {
childList
.stream()
.filter(c -> p.id() == c.parentId())
.<...continue working on stream...>
});
Run Code Online (Sandbox Code Playgroud)
我找不到如何用谓词替换"过滤器"部分的方法,因为我似乎需要将参数传递给Predicate?
你的问题是你每次都使用不同的谓词,因为虽然c是谓词的参数,但p也有所不同:
final Node p;
Predicate<Node> matchesParentId = c -> p.id() == c.id();
Run Code Online (Sandbox Code Playgroud)
您的现有代码编译正常的原因是在块的范围内实际上p是最终的forEach,因此它可以用作Predicate该范围内的最终字段,具有一次forEach迭代的生命周期.
你可以这样做:
parentList.forEach(p -> {
childList
.stream()
.filter(matchesId(p))
.<...continue working on stream...>
});
private Predicate<Node> matchesId(Node other) {
return node -> node.id() == other.id();
}
Run Code Online (Sandbox Code Playgroud)
但是你将无法创建一个Predicate并重新使用它p.
你可以写一个BiPredicate和咖喱成一个Predicate.不幸的是,Java不提供咖喱方法,因此您必须提供自己的方法.
private <T,U> Predicate<U> curry(BiPredicate<T,U> biPredicate, T t) {
return u -> biPredicate.test(t, u);
}
BiPredicate<Node,Node> nodesMatch = (a,b) -> a.id() == b.id();
parentList.forEach(p -> {
childList
.stream()
.filter(curry(nodesMatch, p))
.<...continue working on stream...>
});
Run Code Online (Sandbox Code Playgroud)
除了之前的解决方案之外,这并没有给你带来太大的收获,但它更像是一个FP-nerdy.你还在Predicate为每个人创造新的东西p.当然你可以内联它而不是使用该curry()方法.
.filter(c -> nodesMatch.test(p, c))
Run Code Online (Sandbox Code Playgroud)
它确实意味着您可以选择BiPredicate<Node,Node>动态插入的s.如果你的BiPredicate初始化成本很高,Predicates那么通过currying缠绕它的很多都会很便宜.
或者,你可以映射p和c成一个单一的对象,它允许你提交整个事情谓词:
Predicate<Pair<Node,Node>> nodesMatch = pair ->
pair.left().id() == pair.right().id();
parentList.forEach(p -> {
childList
.stream()
.map(c -> new Pair<Node>( c, p))
.filter(nodesMatch)
.map( pair -> pair.left() )
.<...continue working on stream...>
});
Run Code Online (Sandbox Code Playgroud)
(Pair这里是假设的,但许多第三方图书馆(例如番石榴)提供一个,或自己动手,或使用new Node[] { c, p })
| 归档时间: |
|
| 查看次数: |
2900 次 |
| 最近记录: |