Java的foreach有啥不同
Posted Danny_姜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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方法删除元素即可,如下所示:
如果你喜欢本文
长按二维码关注
以上是关于Java的foreach有啥不同的主要内容,如果未能解决你的问题,请参考以下文章