Java 8 stream lambda要求变量为final/effectively final,求AtomicBoolean替代方案
方案1:优先使用Stream内置匹配方法(最优)
你的场景本质是判断集合中是否存在name不为空的元素,直接用Stream提供的anyMatch短路操作即可,完全不需要修改外部变量,性能比手动遍历+修改变量更高,遇到第一个符合条件的元素就会终止遍历:
// 直接返回匹配结果,不需要额外维护成员变量 public boolean hasNonNullName() { return list.stream().anyMatch(c -> c.getName() != null); } public void test() { if (hasNonNullName()) { System.out.println("value is there"); } }
方案2:使用类成员变量(适合多方法共享变量的场景)
只有被lambda捕获的局部变量才要求是final或有效final,类的成员变量没有这个限制。如果变量需要在多个类方法间共享,直接用普通boolean作为成员变量即可,不需要原子类包装:
private boolean bool = true; public void testBool() { list.stream().forEach(c -> { if (c.getName() != null) { bool = true; } }); } public void test() { if (bool) { System.out.println("value is there"); } }
注意:如果是并行流场景且存在多线程并发修改的情况,还是需要做同步处理,单线程流无任何性能损耗
方案3:数组包装局部变量(适合方法内局部使用的场景)
如果变量只需要在当前方法内使用,可以用长度为1的数组包装基础类型,数组的引用是不可变的(符合有效final要求),可以直接修改数组内的元素值,单线程场景下性能远高于AtomicBoolean:
public void testBool() { // 长度为1的boolean数组,引用是final的 boolean[] boolHolder = {true}; list.stream().forEach(c -> { if (c.getName() != null) { boolHolder[0] = true; } }); // 方法内后续直接使用boolHolder[0]即可 if (boolHolder[0]) { System.out.println("value is there"); } }
注意:该方案仅适用于单线程流,并行流场景下会有线程安全问题
补充说明
AtomicBoolean的性能损耗主要来自于volatile修饰带来的内存屏障开销以及CAS操作的成本,只有在并发编程场景下才需要使用,普通单线程场景完全不需要引入原子类。
内容的提问来源于stack exchange,提问作者Neela
相关产品推荐
相关产品推荐

