3种不同的遍历问题(Iterator,foreach,for))

3种不同的遍历问题

【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。

Iterator

  • 对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。迭代器与枚举有两点不同:

    • ==迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的== collection ==移除元素==。
    • 方法名称得到了改进。

    此接口是 Java Collections Framework 的成员。

  • collection实现了Iterator()方法,所有集合类都能使用集合类

    方法摘要
    boolean hasNext() 如果仍有元素可以迭代,则返回 true
    E next() 返回迭代的下一个元素。
    void remove() ==从迭代器指向的 collection 中移除迭代器返回的最后一个元素==(可选操作)。
  • public interface Iterator<E> 该接口是迭代器

  • 底层是通过指针的挪动来遍历集合元素

  • 遍历期间不能进行增删原集合内容

  • Iterable接口(Collection的父接口)里定义了可以返回Iterator接口的方法iterator()

  • public interface Iterable<T>

    实现这个接口允许对象成为 "foreach" 语句的目标。

    • 只要某个类实现了Iterable接口,这个类就可以被增强for循环(foreach)遍历

      • ==增强for循环的底层是通过迭代器实现。==
      • 遍历期间无法对集合里的元素进行操作
      • 增强for循环是JDK1.5的新特性
  • Iterator遍历删除原理:根据根据在遍历期间改变标记值来间接删除集合元素(这是基于JDK1.8之前的版本解释)

    • 先==复制==一个集合,并且每个元素标记true
    • 调用remove()方法会将true改成false
    • 再遍历结束,会将标记值与原来集合比较,标记为false的会自动删除
      • 如果期间集合元素和原来不同会产生异常ConcurrentModificationException
      • 不能对原集合直接增删-----遍历期间改变原集合,遍历结束会根据标记值和原集合进行状态的对比
     Iterator<String> iterator = v.iterator();
            while(iterator.hasNext()){
                String next = iterator.next();
                //通过迭代器的对象删除遍历已经获取的元素
               /* - 先复制一个集合,并且每个元素标记true
                    调用remove()方法会将true改成false
                    再遍历结束,会将标记值与原来集合比较,标记为false的会自动删除*/
                //iterator.remove();
    
                //通过集合对象删除
                //会删除直接原集合元素
                //遍历结束,比较标记值,与原来内容不同产生异常
                v.remove(next); //ConcurrentModificationException
                System.out.print(next);
            }
    
img
  • foreach:因为foreach的底层也是iterator,而且没有iterator中的remove()方法,所以无法直接对集合里的元素进行删除。
  • 1.原始的for循环删除集合元素的时候有可能会漏掉某个元素
    测试代码:

    /**
    
    - 假设需要删除集合中的所有的"A"元素
    - 如果使用原始的for循环,那么就可能会漏删
      */
    List<String> list = new ArrayList<>();
    list.add("A");
    list.add("A");
    list.add("B");
    for(int i=0; i<list.size(); i++) {
      if("A".equals(list.get(i))) {
          list.remove(i);
      }
    }
    System.out.println(list);
    

    输出结果:
    [A, B]
    可以看到集合中只有一个"A"被删了,第二个"A"却还在。

    img

    其实解决办法也很简单,在删除元素之后再加一行代码i--就解决了

  • 题外:Vector中有elements()方法,存在最古老的迭代器Enumeration
//用于遍历,返回最古老的迭代器 ,只存在于Voctor,原码
public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {  //放在while循环,判断是否还有元素
                return count < elementCount;
            }

            public E nextElement() {  //用于获取元素
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }

 /*  //调用Elements方法返回迭代器,测试
        //会默认把Vector对象身上所有元素放到迭代器上
        Enumeration<String> elements = v.elements();

        //迭代遍历
        while(elements.hasMoreElements()){//判断是否还有元素
            //获取元素
            String str = elements.nextElement();
            System.out.print(str);
        }
*/
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容