首先它们的功能都是遍历数组每个元素并执行入参的accept方法,但是它们的实现方式却不一样,在一些特定的情况下,执行会出现不同的结果。
区别
list.forEach()使用增强的for循环(默认)
ArrayList自己实现了forEach
list.stream().forEach()它首先将集合转换为流,然后对集合的流进行迭代
差异
一、元素遍历的顺序
list.forEach的增强for循环使用集合的迭代器Iterator来遍历元素,相当于这样。
List<String> list = Arrays.asList("A", "B","C");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
而List和Iterator都是接口,那么我们可以实现List的iterator()和Iterator的next(),这样就可以改变遍历的顺序了,而list.stream().forEach()则不行。
public class CustomerList extends LinkedList<String> {
@Override
public Iterator<String> iterator(){
Iterator<String> it = new Iterator<String>(){
private int currentIndex;
@Override
public boolean hasNext(){
return currentIndex <= 10;
}
@Override
public String next(){
currentIndex++;
return "A";
}
@Override
public void remove(){
throw new UnsupportedOperationException();
}
};
return it;
}
public static void main(String[] args) {
List<String> list = new CustomerList();
list.add("A");
list.add("B");
list.add("C");
list.forEach(System.out::print);
System.out.println(" ");
list.stream().forEach(System.out::print);
}
}
结果不一样
二、元素的删除
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("A");list.add("B");list.add("C");list.add("D");
try {
list.forEach(item -> {
System.out.println(item);
list.remove(0);
});
} catch (Exception e) {
e.printStackTrace();
}
list.stream().forEach(item -> {
System.out.println(item);
list.remove(0);
});
}
当一边遍历一边删除的时候,forEach能够快速失败,而stream().forEach()只有等到数组遍历完之后才会抛异常。
结论
为了避免不必要的麻烦,在单纯只想迭代集合的场景下,应该直接使用forEach。
补充
1. map.forEach() (默认)
HashMap、LinkedHashMap、ConcurrentHashMap都有自己的forEach实现。
2. stream()是Collection接口的一个方法,但是Map接口并没有继承Collection,所以Map没有map.stream().forEach()