文章转载自「开发者圆桌」一个关于开发者入门、进阶、踩坑的微信公众号

在Java中,遍历集合和数组一般有以下三种形式:

for (int i = 0; i < list.size(); i++) {

System.out.print(list.get(i) + ",");

}

Iterator iter= list.iterator();

while (iter.hasNext()) {

System.out.print(iter.next() + ",");

}

for (Integer i : list) {

System.out.print(i + ",");

}

第一种是普通的for循环遍历,第二种是使用迭代器进行遍历,第三种我们一般称之为增强for循环也就是for each循环。

for each实现原理剖析

我们对以下代码进行反编译:

for(String str:list){

System.out.print(str+",");

}

反编译后的代码是这样的:

String str;

for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.print((new StringBuilder(String.valueOf(str))).append(",").toString())){

str = (String)iterator.next();

}

反编译后的代码虽然有点复杂,不过通过反编译,我们看到Java中的for each循环底层是通过迭代器模式来实现的。

坑,小心哦

由于for each循环通过迭代器实现,那么必然有迭代器的特性。在Java中使用迭代器遍历元素的时候,在对集合进行删除的时候一定要注意,使用不当有可能发生ConcurrentModificationException,如以下代码:

for(String str:list){

System.out.print(str+",");

list.remove(str);

}

会抛出ConcurrentModificationException异常。

Iterator被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,当索引指针往后移动的时候就找不到要迭代的对象,所以会抛出ConcurrentModificationException异常。

Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

正确的在遍历的同时删除元素的姿势:

Iterator<String> Iter = list.iterator();

while (Iter.hasNext()) {

String str=Iter.next();

System.out.print(str+",");

//注意不是list而是Iter的remove。

Iter.remove();

}

这个细微的问题,可能在大部分情况下由于条件的限制不会出现,一旦条件满足,问题便暴露出来,这就是为什么明明运行良好的代码突然报错了。因此在使用for each循环时一定要注意这个坑。


延伸阅读

我们在最初学习Java的时候,会接触到两个命令:javac和java,那个时候我们就知道,javac是用来编译Java类的,就是将我们写好的helloworld.java文件编译成helloworld.class文件。

那么反编译呢,就是通过helloworld.class文件得到java文件(或者说是程序员能看懂的Java文件)。

常用的反编译工具有jad、jd-gui等,本文使用的是jad,可以去https://varaneckas.com/jad/下载该工具。

Java中的for each实现原理与坑的更多相关文章

  1. Java中的HashMap的工作原理是什么?

    问答题23 /120 Java中的HashMap的工作原理是什么? 参考答案 Java中的HashMap是以键值对(key-value)的形式存储元素的.HashMap需要一个hash函数,它使用ha ...

  2. 深入理解Java中的HashMap的实现原理

    HashMap继承自抽象类AbstractMap,抽象类AbstractMap实现了Map接口.关系图例如以下所看到的: Java中的Map<key, value>接口同意我们将一个对象作 ...

  3. Java 中的监控与管理原理概述

    点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 程序猿阿朗博客 已经收录,有很多知识点和系列文章. 当前 ...

  4. JAVA中堆栈和内存分配原理

    1.栈.堆 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量 ...

  5. Java中Atomic包的实现原理及应用

    1. 同步问题的提出 假设我们使用一个双核处理器执行A和B两个线程,核1执行A线程,而核2执行B线程,这两个线程现在都要对名为obj的对象的成员变量i进行加1操作,假设i的初始值为0,理论上两个线程运 ...

  6. Java中线程池的实现原理

    知识点总结 ---------------------------------------------------------------------------------------------- ...

  7. java中异常处理机制的简单原理

    以上是自认为的java异常处理的简单原理,如有不妥之处还请各位大神帮忙指点,谢谢!

  8. Java 中冷门的 synthetic 关键字原理解读

    看JAVA的反射时,看到有个synthetic ,还有一个方法isSynthetic() 很好奇,就了解了一下: 1.定义 Any constructs introduced by a Java co ...

  9. Java中线程池的实现原理-求职必备

    jdk1.5引入Executor线程池框架,通过它把任务的提交和执行进行解耦,只需要定义好任务,然后提交给线程池,而不用关心该任务是如何执行.被哪个线程执行,以及什么时候执行. 初始化线程池(4种) ...

随机推荐

  1. 才一年,H5的发展就成这样了......

    关于H5的发展,分享几个最近看到的惊人数据和新闻: 1.截至2015,有80%的App将全部或部分基于HTML5.这意味着大部分App的内容都将是以网页的形式呈现,典型的例子包括微信.Facebook ...

  2. WebSocket协议再认识

    WebSocket出现之前 在线聊天室.在线客服系统.评论系统.WebIM等这些应用有一个共同点,就是用户不需要去刷新浏览器就能够从服务器获得最新的数据,这就用到了推送技术. WebSocket出现之 ...

  3. MyBatis 一对一关联查询

    xml文件: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC & ...

  4. Javascript 继承 图形化展示

      <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" conte ...

  5. python之FTP程序(支持多用户在线)

    转发注明出处:http://www.cnblogs.com/0zcl/p/6259128.html 一.需求 1. 用户加密认证 (完成)2. 允许同时多用户登录 (完成)3. 每个用户有自己的家目录 ...

  6. JS 与 OC

    做项目需要从网页点击跳转到app的一个页面上,并且需要获取参数. 当时后台给写的参数是这样的.自己打开浏览器看的源码 JavaScript:window.location.href=   这句话在js ...

  7. bootstrap_下拉菜单+头部

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. webkit 渲染机制

    最近看了< webkit技术内幕 >,虽然并不能完全看懂,但是对浏览器的渲染机制也算是有了一个比较完整的认识. 我们从浏览器地址栏输入网址开始到web页面被完整的呈现在眼前,大概的经过了这 ...

  9. Java LinkedList特有方法程序小解 && 使用LinkedList 模拟一个堆栈或者队列数据结构。

    package Collection; import java.util.LinkedList; /* LinkedList:特有的方法 addFirst()/addLast(); getFirst( ...

  10. 【异构计算】GPU与CPU

    引言 CPU和GPU都是具有运算能力的芯片.CPU更像“通才”主要指令运算(执行)为重和数值运算,而GPU更像“专才”,主要图形类数值计算为核心.在不同类型的运算方面的速度也就决定了它们的能力.芯片的 ...