• 迭代器删除集合中的元素


    刚开始接触遇到一个基础问题:在for循环中删除元素。抛出的异常是"java.util.ConcurrentModificationException"。

    此处梳理总结一下:

      1、模拟异常

     1 @Test
     2 public void testException() {
     3         List<String> list = new ArrayList<>();
     4         list.add("a");
     5         list.add("b");
     6         list.add("c");
     7         list.add("d");
     8         list.add("e");
     9         for (String str : list) {// 当第一个元素被删除后,此处会抛出异常
    10             if ("c".equals(str)) {
    11                 list.remove("c");
    12          }
    13      }
    14  }

      执行后抛出异常:

          java.util.ConcurrentModificationException
          at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
          at java.util.ArrayList$Itr.next(ArrayList.java:851)
          at sometest.loop.IteratorDemo.testException(IteratorDemo.java:69)
          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

      2、解决上面异常的方法 可以用迭代器iterator :  

     1 public static void main(String[] args) {
     2         List<String> list = new ArrayList<>();
     3         list.add("a");
     4         list.add("b");
     5         list.add("c");
     6         list.add("d");
     7         list.add("e");
     8         // 使用迭代器实现删除元素
     9         Iterator<String> it = list.iterator();
    10         while (it.hasNext()) { // 调用hasNext方法判断是否有元素
    11             if ("c".equals(it.next())) { // 获取当前元素
    12                 // 因为使用迭代器的remove方法,指针会同时减一 即就不会因为出现集合的元素和指针数不等抛出异常的问题
    13                 it.remove();
    14             }
    15         }17         list.forEach(s -> System.out.println(s));
    18     }

      执行后输出结果:

                a
                b
                d
                e

      3、除了iterator还可以使用ListIIterator进行遍历删除。两者之间的区别在后续介绍。

     1 @Test
     2 public void testListIterator() {
     3         List<String> list = new ArrayList<>();
     4         list.add("a");
     5         list.add("b");
     6         ListIterator<String> it = list.listIterator();
     7         while (it.hasNext()) { // 调用hasNext方法判断是否有元素
     8             // 通过下面两种方法可以得到当前元素的索引位置
     9             System.out.println("当前元素是:" + it.next());
    10             System.out.println("下一个元素的索引:" + it.nextIndex());
    11             System.out.println("上一个元素的索引:" + it.previousIndex());
    12         }
    13         // listIterator有add()方法
    14         it.add("ff");
    15         list.forEach(s -> System.out.println(s));
    16 }

      执行后输出结果:        

          当前元素是:a
          下一个元素的索引:1
          上一个元素的索引:0
          当前元素是:b
          下一个元素的索引:2
          上一个元素的索引:1
          遍历后元素输出:
                  a
                  b
                  ff

      集合的iterator和ListIterator的区别:

        凡是实现类Collection接口的集合类,都有一个Iterator方法,用于返回一个实现了Iterator接口的对象,用于集合遍历;(iterator接口定义了3个方法分别是hasNext(),next(),remove())

        我们在使用集合List和Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator。在使用过程中不需要干涉其遍历过程,只需要每次取出一个你想要的的数据进行处理就可以了。

      但是在有的时候使用也是有不同的。List和Set都有iterator()来取得迭代器。对于List来说,你也可以通过listIterator()取得迭代器,两种迭代器在有些时候是不能通用的,iterator和ListIterator

      的区别主要是以下方面:

        1.  iterator()方法在set和List接口中都有定义,但是ListIterator()仅存在于list接口中 (或实现类中);

        2.  ListIterator有add()方法,可以向List中添加对象,而Iterator不能。

        3.  ListIterator有Iterator都有的hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()方法和previous方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

        4.  ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

        5.  都可实现删除对象,但是ListIterator可以实现对对象的修改(set方法可以实现) Iterator没有此功能。

        因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。

      因为java8的引入可以在删除元素的时候有了更简便的方法:

        从JDK1.8开始,可以使用removeIf()方法来代替 Iterator的remove()方法实现一边遍历一边删除。

     1 @Test
     2 public void testJava8RemoveIf() {
     3         List<String> list = new ArrayList<>();
     4         list.add("a");
     5         list.add("b");
     6         list.add("c");
     7         list.add("d");
     8         list.add("e");
     9         list.removeIf(s->"c".equals(s));
    10         list.forEach(s-> System.out.print(s + " "));
    11 }

      输出结果:

        a b d e 

  • 相关阅读:
    CCF-CSP题解 201509-4 高速公路
    CCF-CSP题解 201403-4 无线网络
    CCF-CSP题解 201512-4 送货
    2019年9月10日
    53. 最大子序和
    54. 螺旋矩阵
    59. 螺旋矩阵 II
    61. 旋转链表
    62. 不同路径
    70. 爬楼梯
  • 原文地址:https://www.cnblogs.com/lsy-bolg/p/13274959.html
Copyright © 2020-2023  润新知