我有Stream<SomeClass> stream
而SomeClass
有布尔方法isFoo()
和isBar()
。
我想检查流中的所有元素是否isFoo()
和isBar()
都等于true
。我可以通过SomeClass:isFoo
和SomeClass::isBar
lambdas单独检查这个条件。
但是我如何将这两个lambdas与and
/ &&
等逻辑运算符结合起来?
一个显而易见的方法是写一个额外的lambda:
stream.allMatch(item -> item.isFoo() && item.isBar());
但是我想避免写一个额外的lambda。
另一种方法是转发Predicate<? super SomeClass>
:
stream.allMatch(((Predicate<? super SomeClass>) SomeClass::isFoo).and(SomeClass::isBar));
有没有更好的方法 - 没有演员表和明确的lambdas?
答案 0 :(得分:12)
如果有假设的Predicate.of
方法,您可以写:
stream.allMatch(Predicate.of(SomeClass::isFoo).or(SomeClass::isBar));
它不存在,但您可以自己编写。
public final class Predicates {
public static <T> Predicate<T> of(Predicate<T> predicate) {
return predicate;
}
}
那就是说,我个人会选择你的第一个选择。
stream.allMatch(item -> item.isFoo() && item.isBar());
::
方法引用很好,但有时你必须编写显式的lambdas。
答案 1 :(得分:7)
这可能没有资格作为答案(如果没有,请不要投票),但我有点有同样的需要,把一些谓词捏在一起我只是为此写了一个小实用程序。
private static <T> Predicate<T> andPredicates(Predicate<T>... predicates) {
return Arrays.stream(predicates).reduce(Predicate::and).orElse(x -> true);
}
答案 2 :(得分:0)
您一定要使用Stream的过滤器方法。过滤器选择与给定谓词匹配的列表元素。
此行同时选择Foo和Bar的元素:
list.stream().filter(SomeClass::isFoo).filter(SomeClass::isBar)
输出是Stream,因此您应该收集List中的元素以实际使用它们:
list.stream().filter(SomeClass::isFoo).filter(SomeClass::isBar).collect(Collectors.toList());
为了检查流的所有元素是否都是Foo和Bar,您可以将原始列表的大小与过滤流的大小进行比较:
public static Boolean isFooBar(List<SomeClass> list) {
return list.size() == list.stream().filter(SomeClass::isFoo).filter(SomeClass::isBar).count();
}
答案 3 :(得分:0)
您可以过滤并仅收集列表的大小并与原始列表进行比较:
long count = list.stream().filter(SomeClass::isFoo).filter(SomeClass::isBar).collect(Collectors.counting());