zoukankan      html  css  js  c++  java
  • 对List遍历过程中添加和删除的思考

    对List遍历过程中添加和删除的思考

    平时开发过程中,不少开发者都遇到过一个问题:在遍历集合的的过程中,进行add或者remove操作的时候,会出现2类错误,包括:
    java.util.ConcurrentModificationException for in遍历过程中add/remove导致的错误
    java.lang.IndexOutOfBoundsException 越界错误,for循环的时候删除元素。
    最佳实践

    add操作:利用原生的for循环。remove操作利用foreach操作。如下所示:
    //OK,利用 iterator 和 其remove 方法
    @Test
    public void testIteratorRemove2() {
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
    if ("3".equals(iterator.next())) {
    iterator.remove();
    }
    }
    System.out.println(list);
    }

    //OK 利用for循环。
    @Test
    public void testForAdd() {
    for (int i = 0, length = list.size(); i < length; i++) {
    if (list.get(i).equals("2")) {
    list.add("2");
    }
    }
    }
    经典错误1

    如下代码本意是:通过iterator的方式从头到尾变遍历list中的元素。
    @Test
    public void testIteratorRemove2() {
    while (list.iterator().hasNext()) {
    System.out.println(list.iterator().next());
    }
    }
    但是该段代码永远都会输出 list的第一元素,为什么?关键错误在链式写法上:
    while (list.iterator().hasNext()) {}
    每次循环时候先调用了list.iterator() 在该方法中每次都是重新new了一个新的对象
    public Iterator<E> iterator() {
    return new Itr();
    }
    所以每一次都是一个新的遍历对象,所以输出第一个元素。
    那么为什么每次都要new一个新的Itr()?我猜想应该是为了并发的读,每次读的都是一份独立的数据,避免多个并发读的时候,出现当前指针问题。
    处理办法:将list.iteraotr() 放在外面即可,保证循环中循环的是1个对象。
    @Test
    public void testIteratorRemove2() {
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
    if ("3".equals(iterator.next())) {
    iterator.remove();
    }
    }
    System.out.println(list);
    }
    经典错误2

    // 死循环
    @Test
    public void testForAdd2() {
    for (int i = 0; i < list.size(); i++) {
    if (list.get(i).equals("3")) {
    list.add("3");
    }
    }
    }
    当if条件满足的时候,该方法永远不会结束,为什么?
    对于for循环 for (int i = 0; i < list.size(); i++)有3个部分,第一个部分为初始化,只执行一次。第二个部分每次都会执行,第三个部分也是每次都会执行。
    上述问题的第二步会导致无限循环:因为for中每一次循环都会在list添加了一个元素,每次步进为1,内部元素也是每次都加1.
    如何处理该问题: list.size()放在第一部分,第一部分只初始化一次。
    //OK 利用for循环。
    @Test
    public void testForAdd() {
    for (int i = 0, length = list.size(); i < length; i++) {
    if (list.get(i).equals("2")) {
    list.add("2");
    }
    }
    }
    经典错误3

    //java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    @Test
    public void testForRemove() {
    for (int i = 0, length = list.size(); i < length; i++) {
    if (list.get(i).equals("3")) {
    list.remove("3");
    }
    }
    }
    该错误在list.add("3")的时候就不会发生该错误,具体原因是什么?
    Liu CF:转载请保留原文链接,3Q!

  • 相关阅读:
    echarts基础使用
    将数据表中的热词统计结果用echarts热词云展示
    LInux下bash: wget: command not found解决方法
    利用Jieba对txt进行分词操作并保存在数据库中
    idea运行Guns示例demo
    浅谈一下mshta在CVE201711882里的命令构造
    CVE201711882 POC 全版本通杀
    本地复现Flash 0day漏洞(CVE20184878)
    Oracle安装错误
    oracle远程连接服务器出现 ORA12170 TNS:连接超时 解决办法
  • 原文地址:https://www.cnblogs.com/LiuChunfu/p/8482882.html
Copyright © 2011-2022 走看看