注意:该问题与java.util.Optional
无关。
在处理流时,我经常使用如下逻辑:
Stream<FooBar> stream = myInitialStream();
if (needsFilter1) stream = stream.filter(c -> whatever1());
if (needsFilter2) stream = stream.filter(c -> whatever2());
...
return stream.collect(toList());
我要实现的目标是使用链接将上面的代码转换为单个表达式。我发现这更具可读性和直截了当。 到目前为止,我发现实现这一目标的唯一方法是:
return myInitialStream()
.filter(needsFilter1? c->whatever1() : c->true)
.filter(needsFilter2? c->whatever2() : c->true)
.collect(toList());
仍然,这将对那些琐碎的c->true
lamda进行不必要的调用,这可能会在扩展时产生一些性能成本。
所以我的问题是:有没有更好的方法来生成包含可选过滤的链式流表达式?
更新:也许我没有说得足够清楚,但是我的问题的重点是找到一个单表达式解决方案。如果我必须使用多个语句(例如,初始化谓词),那么我也可以使用问题的第一个代码块,该代码块实际上是相同的。
答案 0 :(得分:11)
使用Predicate::and
返回新的谓词,根据条件约束谓词。
Predicate<FooBar> predicate = c -> whatever();
if (condition1) { predicate = predicate.and(c -> whatever1()); }
if (condition2) { predicate = predicate.and(c -> whatever2()); }
List<FooBar> dest = list.stream()
.filter(predicate)
.collect(Collectors.toList());
在更新时请求单个表达式。无论如何,您需要一个映射条件的来源。在数据结构Map<Supplier<Boolean>, Predicate<Integer>>
中,键是条件的Supplier
,用于决定是否应使用值(Predicate<FooBar>
)。
通过将这些Predicate<FooBar>
与Predicate::and
链接起来,将它们的映射Predicates
返回Supplier<Boolean>
(将条件{有效)。
具有true
个条件:
Map
这里是一个Map<Supplier<Boolean>, Predicate<FooBar>> map = new HashMap<>();
map.put(() -> needsFilter1, c -> whatever1());
map.put(() -> needsFilter2, c -> whatever2());
...
语句:
Stream
答案 1 :(得分:4)
我的解决方案有点晚了,无论如何,我会把它留在这里。
我有个想法,想写一个构建器来构建一个复杂的Predicate
,但最终得到了一个类FilterCondition
和一个方法FilterCondition.combine
。
Stream.of("123", "1", "12345", "", "12", "", "2")
.filter(FilterCondition.<String>combine(
FilterCondition.of(() -> true, s -> s.contains("3")),
FilterCondition.of(() -> true, s -> s.contains("2")),
FilterCondition.of(() -> false, s -> s.isEmpty())
).toPredicate())
.collect(Collectors.toList());
通过静态导入FilterCondition.of
和FilterCondition.combine,
,它看起来会更好。
Stream.of("123", "1", "12345", "", "12", "", "2")
.filter(combine(
of(() -> true, s -> s.contains("3")),
of(() -> true, s -> s.contains("2")),
of(() -> false, String::isEmpty)
).toPredicate())
.collect(Collectors.toList());
FilterCondition<T>
基本上是Predicate<T>
,带有附加条件,用于检查是否应应用predicate
。
FilterCondition.combine
花费了FilterCondition
并组成了一个。
class FilterCondition<T> {
private final Supplier<Boolean> filterEnabled;
private final Predicate<T> predicate;
private FilterCondition(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
this.filterEnabled = filterEnabled;
this.predicate = predicate;
}
public static <T> FilterCondition<T> of(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
return new FilterCondition<>(filterEnabled, predicate);
}
@SafeVarargs
public static <T> FilterCondition<T> combine(FilterCondition<T>... conditions) {
return new FilterCondition<>(
() -> true,
Arrays.stream(conditions).filter(i -> i.filterEnabled.get()).map(i -> i.predicate).reduce(Predicate::and).orElse(t -> true)
);
}
public Predicate<T> toPredicate() {
return predicate;
}
}