最简单的解决方案(除了将所有内容保留为更容易之外)是创建三个单独的流:
Set<MyObj> set1 = inputSet.stream().filter(pred1).collect(Collectors.toSet());Set<MyObj> set2 = inputSet.stream().filter(pred2).collect(Collectors.toSet());Set<MyObj> set3 = inputSet.stream().filter(pred3).collect(Collectors.toSet());
如果有谓词列表,则可以创建相应的集合列表:
List<Predicate<MyObj>> predicates = Arrays.asList(pred1, pred2, pred3);List<Set<MyObj>> result = predicates.stream() .map(pred -> inputSet.stream().filter(pred).collect(Collectors.toSet())) .collect(Collectors.toList());
在此,结果列表中的第一个集合对应于第一个谓词,依此类推。
如果您真的想单次处理输入(无论出于何种原因),则可以为此编写一个特殊的收集器。这是很普遍的一种:
public static <T, A, R> Collector<T, ?, List<R>> multiClassify( List<Predicate<T>> predicates, Collector<? super T, A, R> downstream) { Supplier<A> dsSupplier = downstream.supplier(); BiConsumer<A, ? super T> dsAccumulator = downstream.accumulator(); BinaryOperator<A> dsCombiner = downstream.combiner(); Supplier<List<A>> supplier = () -> Stream.generate(dsSupplier) .limit(predicates.size()).collect(Collectors.toList()); BiConsumer<List<A>, T> accumulator = (list, t) -> IntStream .range(0, predicates.size()).filter(i -> predicates.get(i).test(t)) .forEach(i -> dsAccumulator.accept(list.get(i), t)); BinaryOperator<List<A>> combiner = (l1, l2) -> IntStream.range(0, predicates.size()) .mapToObj(i -> dsCombiner.apply(l1.get(i), l2.get(i))) .collect(Collectors.toList()); Characteristics[] dsCharacteristics = downstream.characteristics().toArray( new Characteristics[0]); if (downstream.characteristics().contains(Characteristics.IDENTITY_FINISH)) { @SuppressWarnings("unchecked") Collector<T, ?, List<R>> result = (Collector<T, ?, List<R>>) (Collector<T, ?, ?>) Collector.of(supplier, accumulator, combiner, dsCharacteristics); return result; } Function<A, R> dsFinisher = downstream.finisher(); Function<List<A>, List<R>> finisher = l -> l.stream().map(dsFinisher).collect(Collectors.toList()); return Collector.of(supplier, accumulator, combiner, finisher, dsCharacteristics);}它获取谓词列表,并返回每个谓词的下游收集器结果列表。用法示例:
List<String> input = asList("abc", "ade", "bcd", "cc", "cdac");List<Predicate<String>> preds = asList( s -> s.length() == 3, s -> s.startsWith("a"), s -> s.endsWith("c"));List<Set<String>> result = input.stream().collect(multiClassify(preds, Collectors.toSet()));// [[bcd, abc, ade], [abc, ade], [cc, abc, cdac]]


