如何将多个谓词应用于java.util.Stream? [英] How to apply multiple predicates to a java.util.Stream?
问题描述
如何将多个谓词应用于 java.util.Stream的
filter()
方法?
How can I apply multiple predicates to a java.util.Stream's
filter()
method?
这就是我现在所做的,但我并不喜欢它。我有一个集合
的东西,我需要根据过滤器(谓词)的集合
来减少事物的数量:
This is what I do now, but I don't really like it. I have a Collection
of things and I need to reduce the number of things based on the Collection
of filters (predicates):
Collection<Thing> things = someGenerator.someMethod();
List<Thing> filtered = things.parallelStream().filter(p -> {
for (Filter f : filtersCollection) {
if (f.test(p))
return true;
}
return false;
}).collect(Collectors.toList());
我知道如果我事先了解过滤器的数量,我可以这样做:
I know that if I knew number of filters up-front, I could do something like this:
List<Thing> filtered = things.parallelStream().filter(filter1).or(filter2).or(filter3)).collect(Collectors.toList());
但是如何在不混合编程风格的情况下应用未知数量的谓词?要知道它看起来有点丑......
But how can I apply unknown number of predicates without mixing programming styles? For know it looks sort of ugly...
推荐答案
我假设您的过滤器
是一种与 java.util.function.Predicate
不同的类型,这意味着它需要适应它。一种可行的方法如下:
I am assuming your Filter
is a type distinct from java.util.function.Predicate
, which means it needs to be adapted to it. One approach which will work goes like this:
things.stream().filter(t -> filtersCollection.stream().anyMatch(f -> f.test(t)));
这会为每个谓词评估重新创建过滤器流带来轻微的性能损失。为了避免这种情况,你可以将每个过滤器包装成谓词
并组成它们:
This incurs a slight performance hit of recreating the filter stream for each predicate evaluation. To avoid that you could wrap each filter into a Predicate
and compose them:
things.stream().filter(filtersCollection.stream().<Predicate>map(f -> f::test)
.reduce(Predicate::or).orElse(t->false));
但是,现在每个过滤器都在它自己的 Predicate $ c后面$ c>,引入一个更多级别的间接,不明确哪种方法会有更好的整体表现。
However, since now each filter is behind its own Predicate
, introducing one more level of indirection, it is not clear-cut which approach would have better overall performance.
没有适应性考虑(如果你的过滤器
碰巧是谓词
)问题陈述变得简单得多,第二种方法明显胜出:
Without the adapting concern (if your Filter
happens to be a Predicate
) the problem statement becomes much simpler and the second approach clearly wins out:
things.stream().filter(
filtersCollection.stream().reduce(Predicate::or).orElse(t->true)
);
这篇关于如何将多个谓词应用于java.util.Stream?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!