
本文共 2323 字,大约阅读时间需要 7 分钟。
Java Script forEach 方法详解
forEach 方法介绍
forEach 是 JavaScript 中一个非常有用的迭代方法,用于遍历数组或 Map 中的条目。该方法通过传递一个函数来执行特定的操作,直到所有条目都被处理或遇到异常。
方法定义
default void forEach(BiConsumer action)
方法说明
forEach 方法接收一个 BiConsumer 作用对象,该对象接收两个参数:一个 key 和一个 value(即 Map 中的条目)。默认实现会按进入设置迭代的顺序依次执行 action。需要注意的是,默认实现不会保证线程安全和原子性,想要保证并发安全的实现必须覆盖这个方法并记录其并发特性。
参数说明
- action: 要为每个条目执行的操作。若 action 为 null 或空,则会抛出 NullPointerException。
异常处理
- 如果在迭代期间发现条目被删除,会抛出 ConcurrentModificationException。
最低版本
forEach 方法从 Java 1.8 开始提供支持。
测试示例
以下示例展示了如何在 Java 1.8 及以上版本中使用 forEach 方法遍历 Map:
@Testpublic void testMapForEach { Mapmap = new HashMap<>(); map.put("name", "tom"); map.put("age", "11"); map.put("email", "xxx@126.com"); //传统迭代方式 for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } //forEach 的优雅写法 map.forEach((k, v) -> { System.out.println(k + ":" + v); });}
代码解读
forEach 方法通过接收一个 BiConsumer 对象来执行操作。在传统迭代方式中,我们需要手动获取每个条目的 key 和 value 并执行操作。而在 forEach 中,只需要传递 lambda 表达式即可,大大简化了代码书写。
forEach 源码解析
从源码可以看出,forEach 方法在传统的迭代方式上仅仅增加了层壳,使得代码更加优雅且易于阅读。源码主要包含以下几个部分:
default void forEach(BiConsumer action) { Objects.requireNonNull(action); for (Map.Entryentry : entrySet()) { String key = entry.getKey(); String value = entry.getValue(); try { action.accept(key, value); } catch (IllegalStateException ise) { throw new ConcurrentModificationException(ise); } }}
逐层解释
Objects.requireNonNull(action);
确保 action 不为 null。
使用 entrySet()
获取当前 Map 中的条目集 entrySet()。
在 try-catch 块中获取每个条目的 key 和 value,并将它们传递给 action.accept()。
如果在迭代过程中遇到 IllegalStateException(通常表示条目被删除),会抛出 ConcurrentModificationException。
常见问题解答
为什么推荐使用 forEach 而不是传统的 for-each 进入循环?
forEach 方法的写法更加简洁优雅,适用于大多数 Map 或数组的遍历场景。如果 action 内部修改了 Map,会有什么影响?
forEach 会检测到条目被删除的异常,并抛出 ConcurrentModificationException,避免数据不一致。实际应用示例
假设我们需要遍历一个 String 的数组并将其转换为 Map。可以利用 forEach 方法结合 Map 接口实现:
ListoriginList = Arrays.asList("apple", "banana", "orange");Map map = new LinkedHashMap<>();originList.forEach((s, index) -> { map.put(s, index);});System.out.println(map); // 输出:{apple=0, banana=1, orange=2}
总结
forEach 方法通过简化迭代逻辑和提供更优雅的 API 界面,使得代码更加可读和高效。在实际应用中应根据需求选择是否手动处理异常或自定义迭代顺序。