Java并行流匹配条件即终止、否则收集元素的实现方法咨询
Java并行流短路+收集联合实现方案
方案1:全版本兼容自定义Collector(推荐,并行流安全)
该方案兼容Java 8及以上所有版本,线程安全适配并行流,不会引入额外性能开销,适合象棋引擎这类对性能敏感的场景。
核心思路是通过原子标记位记录终止条件触发状态,元素处理阶段优先检查标记位,触发后直接跳过所有后续操作,最终返回的结果容器会明确标识是否触发短路、以及未触发时的全部分值列表。
代码实现
首先定义结果容器类:
// 结果容器,统一封装短路状态和分值列表 class ScoreResult { private final boolean isTerminated; private final List<Integer> scores; public ScoreResult(boolean isTerminated, List<Integer> scores) { this.isTerminated = isTerminated; this.scores = scores; } // 按需添加getter方法 public boolean isTerminated() { return isTerminated; } public List<Integer> getScores() { return scores; } }
自定义短路收集器:
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collector; import java.util.concurrent.atomic.AtomicBoolean; public static Collector<Integer, ?, ScoreResult> shortCircuitCollector(Predicate<Integer> terminateCondition) { // 原子标记位,并行流下线程安全 AtomicBoolean terminated = new AtomicBoolean(false); return new Collector<Integer, List<Integer>, ScoreResult>() { @Override public Supplier<List<Integer>> supplier() { return ArrayList::new; } @Override public BiConsumer<List<Integer>, Integer> accumulator() { return (list, score) -> { // 已触发短路直接跳过处理 if (terminated.get()) return; // 匹配终止条件则设置标记 if (terminateCondition.test(score)) { terminated.set(true); return; } list.add(score); }; } @Override public BinaryOperator<List<Integer>> combiner() { return (leftList, rightList) -> { // 已触发短路无需合并结果 if (terminated.get()) return leftList; leftList.addAll(rightList); return leftList; }; } @Override public Function<List<Integer>, ScoreResult> finisher() { return list -> new ScoreResult(terminated.get(), Collections.unmodifiableList(list)); } @Override public Set<Characteristics> characteristics() { return Collections.emptySet(); } }; }
调用示例
List<Move> moves = // 你的待处理Move列表 // 自定义终止条件:分值小于4就触发短路 Predicate<Integer> terminateCond = score -> score < 4; ScoreResult result = moves.parallelStream() .map(this::calculateMoveScore) // 你的Move转分值的计算方法 .collect(shortCircuitCollector(terminateCond)); if (result.isTerminated()) { // 触发短路逻辑,无需处理返回的分值列表 } else { List<Integer> allValidScores = result.getScores(); // 执行原逻辑,比如取最大值 int maxScore = Collections.max(allValidScores); }
方案2:Java 9+ 内置短路操作简化实现
如果你使用Java 9及以上版本,可以直接用内置的takeWhile短路操作,配合列表大小校验实现需求,代码更简洁:
List<Move> moves = // 待处理Move列表 // 合法元素判定条件:分值大于等于4 Predicate<Integer> validCond = score -> score >= 4; List<Integer> scores = moves.parallelStream() .map(this::calculateMoveScore) .takeWhile(validCond) .toList(); if (scores.size() != moves.size()) { // 触发短路逻辑 } else { // 拿到全部分值执行后续操作 }
注意:该方案仅适合Move列表无重复、分值计算无副作用的场景,如果存在异常分支建议优先使用方案1
内容的提问来源于stack exchange,提问作者Allen
相关产品推荐
相关产品推荐

