精华内容
下载资源
问答
  • 2021-01-26 13:41:26

    JAVA中循环遍历list有三种方式for循环、增强for循环(也就是常说的foreach循环)、iterator遍历。
    1、for循环遍历list

    for(int i=0;i<list.size();i++){
        if(list.get(i).equals("del"))
            list.remove(i);
    }
    

    这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化,所以会导致你在遍历的时候漏掉某些元素。比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。

    2、增强for循环

    for(String x:list){
        if(x.equals("del"))
            list.remove(x);
    }
    

    这种方式的问题在于,删除元素后继续循环会报错误信息ConcurrentModificationException,因为元素在使用的时候发生了并发的修改,导致异常抛出。但是删除完毕马上使用break跳出,则不会触发报错。

    3、iterator遍历

    Iterator<String> it = list.iterator();
    while(it.hasNext()){
        String x = it.next();
        if(x.equals("del")){
            it.remove();
        }
    }
    

    这种方式可以正常的循环及删除。但要注意的是,使用iterator的remove方法,如果用list的remove方法同样会报上面提到的ConcurrentModificationException错误。

    总结:
      (1)循环删除list中特定一个元素的,可以使用三种方式中的任意一种,但在使用中要注意上面分析的各个问题。
      (2)循环删除list中多个元素的,应该使用迭代器iterator方式。

    更多相关内容
  • 主要介绍了详解Java中list,set,map的遍历增强for循环的相关资料,需要的朋友可以参考下
  • 增强For循环以及集合遍历语法糖
    • 什么是增强For

            增强for循环是for的一种新用法!用来循环遍历数组和集合。优缺点:只能从头到尾的遍历数组或集合,而不能只遍历部分;在遍历List或数组时,不能获取当前元素下标;增强for使用便简单,这是它唯一的优点了; 增强for比使用迭代器方便一点!其实增强for内部是使用迭代器完成的!也就是说,任何实现了Iterable接口的对象都可以被增强for循环遍历!这也是为什么增强for可以循环遍历集合的原因(Collection是Iterable的子接口)。
    注意:Map并没有实现Iterable接口,所以你不能直接使用增强for来遍历它!

    • 增强For测试代码:

            //没有学集合的只需要看1-13行代码
            //传统的数组遍历
            String[] persons = {"张三", "李四", "王五"};
            for (int i = 0; i < persons.length; i++) {
                System.out.println(persons[i]);
            }
            //使用增强for循环的数组遍历
            //这里的String person等价于上面for的int i =0;
            //persons就是你遍历的变量名
            //由于不能取游标所以没有上面的persons[i]那种
            for (String person : persons) {
                System.out.println(person);
            }
            //传统的Iterator遍历集合
            List<String> Listpersons =new ArrayList<String>();
            Listpersons.add("张三");
            Listpersons.add("李四");
            Listpersons.add("王五");
            for(Iterator<String> i=Listpersons.iterator();i.hasNext();){
                String person=i.next();
                System.out.println(person);
            }
            //使用增强For循环遍历集合
            for(String person: Listpersons){
                System.out.println(person);
            }
    • 集合遍历语法糖测试代码

    
            //Persons集合
            List<String> Listpersons =new ArrayList<String>();
            Listpersons.add("张三");
            Listpersons.add("李四");
            Listpersons.add("王五");
         
            //使用语法糖遍历集合
            Listpersons.forEach(System.out::println);

    展开全文
  • foreach循环是计算机编程语言中的一种流程控制语句, 一般用来循环遍历数组跟集合, 获取里面的元素; Java从JDK 1.5开始引入foreach循环, 在遍历集合跟数组, 十分的方便, 也叫作增强for; foreach的语法格式如下图所示...

    foreach循环是计算机编程语言中的一种流程控制语句, 一般用来循环遍历数组跟集合, 获取里面的元素; Java从JDK 1.5开始引入foreach循环, 在遍历集合跟数组, 十分的方便, 也叫作增强for;

    foreach的语法格式如下图所示

    其遍历List的代码如下图所示:

    输出的结果为

    可以从代码看跟输出结果看出来, 使用foreach遍历集合或者数组的时候, 可以起到普通for循环同样的效果, 并且代码格式上更加整洁; 但是作为程序开发人员来说, 只是知道增强for的使用还是不够的, 防止知其然而不知其所以然这样的尴尬局面; 除了熟练应用以外, 更加重要的是要熟悉其原理; 增强for循环是Java提供的一个语法糖(语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会), 将以上代码的class文件反编译后可以看到源码:

    很明显, 所谓的增强for其实是依赖了while循环和Iterator实现的, 那么重点来了, 尝试在foreach循环中对list的元素进行add和moved操作的时候会发生什么?

    首先使用双括弧语法(duble-brace syntax)建立并初始化一个List, 其中包含四个字符串, 分别是Hollis, hollis, HollisChuang, H

    然后使用普通for循环对List进行遍历, 删除List中元素为Hollis的元素, 然后输出List, 结果如下:

    这是使用普通for循环对List中的元素进行操作, 结果输出很正常, 那么再验证一下使用增强for进行操作会是什么结果?

    使用增强for遍历操作List, 会抛出以下异常:

    之所以会抛出这个异常的原因是因为该操作方法触发了一个Java集合的错误检测机制: fail-fast;

    fail-fast, 即快速失败, 它是Java集合的一种错误检测机制; 当多个线程对集合(非fail-safe的集合类)进行结构上的操作的时候, 就有可能产生fail-fast机制, 这个时候就会抛出ConcurrentModificationException(当方法检测到对象的并发修改, 但不允许这种修改时就抛出该异常); 即使在非多线程环境, 单线程操作中违反了规则, 同样也会有可能抛出该异常;

    运行以上代码,同样会抛出异常。看一下ConcurrentModificationException的完整堆栈:

    通过异常堆栈可以看到,异常发生的调用链ForEachDemo的第23行,Iterator.nextI调用了 Iterator.checkForComodification方法 ,而异常就是checkForComodification方法中抛出的。其实,经过debug后,可以发现,如果remove代码没有被执行过,iterator.next这一行是一直没报错的。抛异常的时机也正是remove执行之后的的那一次next方法的调用。

    checkForComodification方法的代码,看下抛出异常的原因:

    代码很明显, 当modCount != expectedModCount的时候, 就会抛出异常

    通过翻源码,可以发现:modCount是ArrayList中的一个成员变量。它表示该集合实际被修改的次数。expectedModCount 是 ArrayList中的一个内部类——Itr中的成员变量。expectedModCount表示这个迭代器期望该集合被修改的次数。其值是在ArrayList.iterator方法被调用的时候初始化的。只有通过迭代器对集合进行操作,该值才会改变。Itr是一个Iterator的实现,使用ArrayList.iterator方法可以获取到的迭代器就是Itr类的实例。

    之间的关系如下

    再往下看, remove方法的核心逻辑如下

    它只修改了modCount,并没有对expectedModCount做任何操作。之所以会抛出ConcurrentModificationException异常,是因为代码中使用了增强for循环,而在增强for循环中,集合遍历是通过iterator进行的,但是元素的add/remove却是直接使用的集合类自己的方法。这就导致iterator在遍历的时候,会发现有一个元素在自己不知不觉的情况下就被删除/添加了,就会抛出一个异常,用来提示用户,可能发生了并发修改。

    那么开发过程中遇到此类场景, 应该如何去正确的使用循环? 

    1, 

    直接使用普通for循环进行操作

    不能在foreach中进行,但是使用普通的for循环还是可以的,因为普通for循环并没有用到Iterator的遍历,所以压根就没有进行fail-fast的检验。

    2, 

    直接使用Iterator进行操作

    除了直接使用普通for循环以外,我们还可以直接使用Iterator提供的remove方法。

    如果直接使用Iterator提供的remove方法,那么就可以修改到expectedModCount的值。那么就不会再抛出异常了。其实现代码如下:

    3, 

    直接使用fail-safe的集合类

    在Java中,除了一些普通的集合类以外,还有一些采用了fail-safe机制的集合类。这样的集合容器在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发ConcurrentModificationException。

    基于拷贝内容的优点是避免了ConcurrentModificationException,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

    4, 

    使用增强for循环其实也可以

    如果,我们非常确定在一个集合中,某个即将删除的元素只包含一个的话, 比如对Set进行操作,那么其实也是可以使用增强for循环的,只要在删除之后,立刻结束循环体,不要再继续进行遍历就可以了,也就是说不让代码执行到下一次的next方法。

     

     

     

     

     

     

     

     

    展开全文
  • 增强for循环遍历List中的元素时,如果循环体中做了删除操作报出如下异常: Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification...

    问题描述

    用增强for循环遍历List中的元素时,如果循环体中做了删除操作报出如下异常:

    Exception in thread "main" java.util.ConcurrentModificationException
    	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    	at java.util.ArrayList$Itr.next(ArrayList.java:859)
    	at test.main(test.java:13)
    

    复现问题

    public class test {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 5; i++){
                list.add(i);
            }
            for (Integer i : list){
                if (i == 4){
                    list.remove(i);
                    System.out.println("remove");
                }
            }
        }
    
    }
    

    看看问题是怎么产生的

    =.=反编译我是不会啦,贴个别人的
    https://blog.csdn.net/puppet121/article/details/81546260
    也就是增强for循环到了虚拟机会变成Iterator执行

    for(java.util.Iterator i$ = list.iterator(); i$.hasNext();)
       {
           String s = (String) i$.next();
           {
               list.remove(s);
           }
       }
    

    先了解modCount:记录对“影响了List size”的操作 次数

    • modCount
      The number of times this list has been structurally modified.
      Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.

    然后看抛异常的地方:

    private class Itr implements Iterator<E> {
    	/**
    	* 这是ArrayList的内部类,Itr在我们执行遍历操作的时候被初始化,expectedModCount = 我们执行的5次插入操作
    	*/
    	int expectedModCount = modCount;
    	
    	public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
    }
    

    然而执行list.remove(Object obj)后,调用的是ArrayList自己的remove方法,虽然modCount+1,但是用于遍历List的itr对象中的expectedModCount依然=5,这样就在遍历下一个元素是就被检查出不一致抛异常啦~

    final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
    

    正确的处理姿势

    		List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 5; i++){
                list.add(i);
            }
            Iterator<Integer> iterator = list.iterator();
            while (iterator.hasNext()){
                int i = iterator.next();
                if (i == 1){
                //要领就是:既然外面用的iterator遍历,那里面也要用iterator删除,这样就保证两个操作数的一致性啦
                    iterator.remove();
                }
            }
    

    --------我是分界线------------
    mentor看代码刚问完会不会有问题 瞬间就抛了异常。。。

    展开全文
  • 1、for循环遍历list for(int i=0;i&lt;list.size();i++){ if(list.get(i).equals("del")) list.remove(i);}这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化,...
  • import java.util.List; public class Add_FOR { public static void main(String[] args) { String[] arr={"hello","你好","你好不好","你很好"}; for (int i=0;i<arr.length;i++){ System.out.println(arr...
  • 方法一:拼接过程中自动处理逗号publicstaticvoidmain(String[]args){StringBuilder str=new StringBuilder();List list=new ArrayList();...i{if(i==list.size()-1)//当循环到最后一个的时候 就...
  • List集合循环遍历

    千次阅读 2022-01-13 10:10:57
    1.增强for循环遍历 2.一般for循环遍历 3.迭代器循环遍历 package com.jpa.demo; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Testssss { public static void...
  • for循环遍历

    2021-06-07 08:57:28
    1、遍历循环 for (循环变量类型 循环变量名称;循环条件;更新语句) 循环体 String[] arr = { “a”, “b”, “c”, “d” }; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } 打印台 a b...
  • 三种for循环遍历

    2021-03-07 23:28:32
    import java.util.ArrayList;import java.util.Iterator;...public class For{public static void main(String[]args) {//new一个集合对象List alList=new ArrayList();alList.add(1);//自动转成Integeral...
  • 增强four循环:底层使用的是迭代器,使用for循环的格式。简化了迭代器的书写,是jdk1.5之后出现的新版本 Collection<... 增强for循环:用来遍历集合和数组; 格式: for(集合/数组的数据类型 变量名 ...
  • java开发过程中,用到的最多...对于ArrayList的遍历,通常是下面的方法: public static void main(String[] args){List arrayList =new ArrayList();for (int i = 0; i < 100; i++)arrayList.add(i);for (int i...
  • 是的首先写一个测试代码:`private void for_Test(){List list =new ArrayList<>();list.add(1);list.add(2);list.add(3);for(int i :list){System.out.println(i);}}`编译成字节码:由于主要是看迭代顺序所以...
  • 增强for循环遍历 数组,Collection,Map

    千次阅读 2018-08-14 09:47:42
    增强for循环:数组,Collection,Map public class Demo { public static void main(String[] args) { /* * 增强for循环:数组,Collection,Map * for(元素类型 变量:数组/Collection){ * 循环体 ...
  • 集合--List集合,增强for循环

    千次阅读 2020-12-15 09:26:24
    什么是集合? 简称集,是用来存储多个元素的容器 集合和数组的区别 元素类型 集合:引用类型(存储基本类型时自动装箱) 数组:基本类型、引用类型 元素个数 集合:不固定,可任意扩容 ...一、List集合
  • 转自:https://blog.csdn.net/changjizhi1212/article/details/81036509JAVA中循环遍历list有三种方式for循环、增强...1、for循环遍历listfor(int i=;iif(list.get(i).equals("del"))list.remove(i);}这种方式的问...
  • import java.util.*; public class ListDemo1 { ... List<Student> list = new ArrayList<Student>(); Student stu1 = new Student("林黛玉", 18); Student stu2 = new Student("西施舌", 18); .
  • 首先是List集合test2的创建和元素的写入: List<String> test2 = new ArrayList<>(); test2.add("1"); test2.add("2"); test2.add("3"); 注意,要用多态的方式创建List集合。 方法一.Iteator...
  • java增强for循环 三种遍历集合方式

    千次阅读 2018-11-10 07:30:09
    java增强for循环 三种遍历集合方式
  • 传统的for循环遍历方式是 //对于数组而言 int[] arr=new int[10]; for(int i=0;i list=new ArrayList(); for(Iterator i=list.iterator();i.hasNext();){ person=i.next(); System.out.println(person); } 现在有了...
  • 增强for循环以及list

    2021-02-17 21:03:20
    addAll()方法参数为一个集合对象,可以将集合对象里的所有元素添加进来 可以通过for循环遍历集合 remove方法删除元素,参数既可以是索引也可以是数据 get方法得到的集合元素是object类型的,不能直接进行运算,需要...
  • 现在我想删除前五个,要求用一次for循环,问问该怎么做到?   我当时想这道题肯定没有那么简单,应该不是常规思路可以解决的。于是,我给出的我的解决思路是,开辟一个集合把后五个元素加入其中,然后覆盖掉原来...
  • 视频地址: Java之增强for循环遍历数组、集合及Map 更多精彩内容,敬请扫码关注(HelloWorld小码农):  
  • Kotlin for循环 when List集合 的用法 1.for循环的四种用法 for(i in 2 .. 5){ } for(i in 5 downTo 2){ } for (i in 1 until 10){ } for(i in 2 .. 5 step 2){ } 2.List 集合 实例化集合 遍历集合 var...
  • 使用for循环遍历的速度会比Iterator遍历的速度要快: for (int i=0, n=list.size(); i < n; i++) list.get(i); runs faster than this loop: for (Iterator i=list.iterator(); i.hasNext();) ...
  • 遍历实现1.迭代器遍历2.普通for循环遍历2.增强for遍历 给出了如何选择遍历方式的些许建议

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 40,768
精华内容 16,307
关键字:

增强for循环遍历list