Java的foreach有啥不同

陈述事实现象

foreach循环

从JDK 5开始,Java可以使用foreach对数组或者实现了Iterator的集合进行遍历。

对上述代码进行反编译,可以得出如下字节码:

可以看出,在编译时期Java编译器对foreach语法进行的字节码优化--使用Iterator对其进行转换。因此上述Java代码等同于如下代码:

注:foreach实际上是一种语法糖,所谓语法糖就是通过编译器或者其它手段对代码进行优化,让开发人员更加方便使用。

透过现象看本质

foreach循环

foreach确实在一定程度上,方便了对集合的遍历操作。但是在实际使用过程中,也是有坑存在的。比如以下代码:

图中红框中代码表示,在遍历集合的同时判断如果num等于1,则删除此元素。但是运行上述代码,会报如下错误:

Itr是ArrayList的内部类,当使用foreach对ArrayList进行遍历时,会通过它进行遍历。在其内部有个安全校验机制就是判断自带变量expectedModCount是否和ArrayList中的变量modCount相等,如果不相等,则直接抛出ConcurrentModificationException异常。

正常遍历的情况下,这两个值是一直相等的;但是如果在遍历时,对ArrayList的元素进行删除操作,则会导致expectedModCount != modCount。

一生二,二生三,三生万物

边遍历,边操作

那该如何实现边遍历边删除呢?刚才我们已经分析出产生ConcurrentModificationException异常的原因是Itr中的变量expectedModCount和ArrayList中的变量modCount不相等,导致Itr调用next方法校验失败。

而造成expectedModCount != modCount的原因是调用了ArrayList.remove方法进行删除操作。

所以如果想实现边遍历边删除,则不能直接调用ArrayList.remove方法。实际上在Itr中已经提供了相对应的remove方法,如下所示:

可以看出在实际上只是在调用ArrayList.remove方法之后,重新将modCount的值赋值给expectedModCount。这样下次调用next方法遍历时,依然可以通过校验。

因此需要手动使用Iterator对ArrayList进行遍历时,同时使用Itertor自身的remove方法删除元素即可,如下所示:


如果你喜欢本文

长按二维码关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值