在 Java 7 里,我们遍历集合的时候一般用的是 Iterable 接口 for each 的方式来操作,较之 fori 循环遍历确实已经提高了很大的效率和可读性。
不过应该有不少新手,在迭代使用不当的时候,遇到过 ConcurrentModificationException 异常。
很多人也会在遍历 Map 的时候一筹莫展,计较于哪种方式效率比较高,在哪种情况下使用哪一种迭代方式。或者有人根本就记不住如何迭代 HashMap,每次都要借助搜索引擎。
不过自从 Java 8 进入 lambda 和 default 时代,这些烦恼将不会存在。
java.lang.Iterable.forEach 和 default
在 Java 8 中,接口中的方法可以被实现。
接口中被实现的方法叫做 default 方法,用关键字 default 作为修饰符来标识。
当一个类实现一个接口的时候,它可以实现已经在接口中被实现过的方法,但这不是必须的。这个类会继承 default 方法。这就是为什么当接口发生改变的时候,实现类不需要做改动的原因。
forEach 方法是 Java 8 中在集合父接口 java.lang.Iterable 中新增的一个 default 实现方法:
default void forEach(Consumer super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
forEach方法接受一个在 Java 8 中新增的 java.util.function.Consumer 的消费行为或者称之为动作(Consumer action )类型;
然后将集合中的每个元素作为消费行为的 accept 方法的参数执行;
直到每个元素都处理完毕或者抛出异常即终止行为;
除非指定了消费行为 action 的实现,否则默认情况下是按迭代里面的元素顺序依次处理。
List 遍历对比
我们通过看一下 java.util.List 的遍历案例,来直观感受一下 Iterable 迭代 迭代和 forEach 遍历的对比。
首先创建一个 ArrayList,存放几个姓名字符串。