Lambda新特性(⼀)--ForEach不能修改外部变量
最近在使⽤java8提供的Lambda新特性,期间也踩了不少坑,这⾥记录⼀下
Lambda新特性–ForEach
java8以前,我们通常⽤对集合的循环都是⼀下⼏种(例⼦:累加)
public void test1() {
List<Integer> list = new ArrayList<>();
int sum = 0;
for (int i = 0;i <= list.size();i++){
sum += (i);
}
}
/
/增强for循环
public void test2() {
List<Integer> list = new ArrayList<>();
int sum = 0;
for (Integer a : list){
sum += a;
}
}
//迭代器循环
public void test3() {
List<Integer> list = new ArrayList<>();
Iterator<Integer> it = list.iterator();
int sum = 0;
while (it.hasNext()){
sum += it.next();
}
}
⽇常开发中最常⽤的就是增强for循环了。⽽到了java8的Lambda表达式中,我⾃然⽽然的根据他的格式进⾏修改:
public void test() {
List<Integer> list = new ArrayList<>();
int sum = 0;
list.forEach(a -> {
sum += a;
});
}
发现他报错:Variable used in lambda expression should be final or effectively final,意思是不允许在Lambda表达式中修改使⽤的(外部)变量。
后来发现了有规避的⽅法但不推荐使⽤,即写⼀个⽅法,在循环中调⽤该⽅法。推荐使⽤ Lambda提供的Steam流的规约操
作,java.util.stream包提供了各种通⽤的和专⽤的规约操作(例如sum、min和max)
public void test3() {
List<Integer> list = new ArrayList<>();
int sum = list.stream()
.mapToInt(e -> e)
.sum();
System.out.println(sum);
}
分析
使⽤lamdba表达式的时候,不能觉得只是for的变种语法⽽已…然后写代码依然按照for怎么循环怎么处理,这样是不对的,毕竟语法的书写⽅式总是跟它的设计⽅式是吻合的。
为什么要禁⽌修改外部变量?
由于这样的写法在多线程的情况下容易产⽣race condition竞态条件,导致结果不正确,除⾮我们能强制保证线程安全,这样引发的问题可能更多。
从设计者⾓度分析,java8提倡⼤家使⽤steam流,让⼤家习惯使⽤规约操作
总结
java8 Lambda 新特性在⼀定程度上提⾼的代码的稳定性和安全性,⽽与以往的版本相⽐,优化的部分
并不是简单的套⽤,需要我⼀
个“坑”⼀个“坑”的去踩。当然,⼤家在在⽇常开发中,可以根据实际情况进⾏选择。⽐如Lambda 的ForEach虽然稳定,但是在性能上⽐增强for循环稍微有所不⾜。
variable used in lambda谢谢!!⼤家⼀起学习,有错之处,请指正!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论