如何通过Java Stream自身映射的引用过滤流?优化两次遍历的初始状态查找
状态机初始状态获取逻辑的优化思路
首先明确:不存在脱离业务逻辑的“零遍历”方案,但可以在保证原有逻辑正确的前提下,把整体执行效率拉到最高,解决原实现的性能问题。
核心优化方向
- 优先替换低效率的查找容器
原实现用List存储所有跳转源状态,每次contains判断都是线性时间复杂度(O(k),k为列表长度),整体时间复杂度是平方级开销。换成HashSet存储相关状态后,单次查找、移除的时间复杂度降为常数级,这部分的性能提升远大于减少一次集合遍历的效果。 - 换用差集思路替代二次遍历过滤
不需要先收集完所有源状态、再二次遍历状态集合逐一判断是否存在,完全可以通过集合差集的逻辑把两步操作合并,减少冗余判断:
这种实现不需要等流完整跑完收集到全量引用列表,再回头二次遍历状态集合做匹配,完全是在流处理过程中逐次拿到引用状态时就完成差集筛选,没有冗余的集合拷贝和判断开销,刚好匹配你提到的“通过流自身映射生成的引用列表完成流过滤、避免多次全量遍历”的目标。public AbstractState getInitialState() { // 初始化状态池:把所有状态放入可变哈希集合 Set<AbstractState> statePool = new HashSet<>(states); // 流处理逐次拿到跳转的from状态,直接从状态池中移除 states.stream() .map(AbstractState::getTransitions) .flatMap(Collection::stream) .map(AbstractStateTransition::getFrom) .forEach(statePool::remove); // 池子里剩下的就是没有被任何跳转引用的初始状态 return statePool.stream() .findFirst() .orElseThrow(NoInitialStateException::new); } - 结构层面的终极优化
状态机的初始状态在状态、跳转关系固定的前提下是完全不变的,根本不需要每次调用方法时重新计算:在状态机初始化完成、所有状态和跳转都注册完毕时,提前计算一次初始状态并缓存,后续调用getInitialState时直接返回缓存值即可,完全消除重复遍历的开销。
注意:只要跳转关系是分散存储在各个状态对象内部的,就不可能完全跳过“扫描所有跳转收集被引用状态”的必要步骤。所有优化的本质都是减少无意义的重复操作、把低效操作换成高效实现,而不是真的能跳过必要的元数据读取。
内容的提问来源于stack exchange,提问作者midorlo
相关产品推荐
相关产品推荐

