如何将Predicate过滤器集合应用到Java Stream流上?
实现方案
完全可以用Java Stream原生API实现,不需要手写循环,有两种常用的Stream风格写法,逻辑和你现有手写循环完全等价,同样保留短路判断特性(遇到第一个不满足的过滤条件就直接终止校验,不会产生多余性能损耗):
方案1:filter中直接使用allMatch(最直观)
直接在Stream的filter方法内对过滤器集合做全匹配校验,无需提前处理过滤器:
final Collection<Predicate<MyObject>> filters = getFilters(); final Stream<MyObject> oStream = getMyObjectStream(); oStream // 只有当前元素满足所有过滤器条件才会通过校验 .filter(obj -> filters.stream().allMatch(predicate -> predicate.test(obj))) .forEach(System.out::println);
空过滤器集合场景下,
allMatch默认返回true,会放行所有元素,符合通用业务逻辑。
方案2:提前合并为单个Predicate(复用性更高)
如果同一组过滤器需要多次使用,可以提前把所有Predicate按逻辑合并成一个总过滤器,后续直接复用即可:
// 按「与逻辑」合并所有过滤器:所有条件满足才通过 Predicate<MyObject> combinedFilter = filters.stream() .reduce(Predicate::and) // 空过滤器集合默认放行所有元素 .orElse(any -> true); // 直接使用合并后的过滤器 oStream.filter(combinedFilter).forEach(System.out::println);
如果你的业务逻辑是「任意过滤器条件满足就通过」,只需把上面的Predicate::and改为Predicate::or,空集合的默认值改为any -> false即可。
扩展:封装工具类模拟filterAll效果
你可以把合并逻辑封装为通用工具方法,用法和你示例中的filterAll几乎一致:
// 通用工具类 public class PredicateUtils { public static <T> Predicate<T> andAll(Collection<Predicate<T>> filters) { return filters.stream().reduce(Predicate::and).orElse(item -> true); } public static <T> Predicate<T> orAll(Collection<Predicate<T>> filters) { return filters.stream().reduce(Predicate::or).orElse(item -> false); } }
使用示例:
oStream.filter(PredicateUtils.andAll(filters)).forEach(System.out::println);
内容的提问来源于stack exchange,提问作者stwissel
相关产品推荐
相关产品推荐

