进阶JAVA篇- Collcetions 工具类与集合的并发修改异常问题

目录

[1.0 集合的并发修改问题](#1.0 集合的并发修改问题)

[1.1 如何解决集合的并发修改问题](#1.1 如何解决集合的并发修改问题)

[2.0 Collcetions 工具类的说明](#2.0 Collcetions 工具类的说明)


1.0 集合的并发修改问题

我们可以简单的认为,就是使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。

代码如下:

java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Abnormal {
    public static void main(String[] args) {

        //创建对象,再添加数据
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("陈七");
        list.add("李麻子");
        list.add("李四");
        list.add("王五");
        //利用迭代器进行遍历,先创建迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String a = iterator.next();
            if (a.contains("李")){
                list.remove(a);
            }
        }
        System.out.println(list);
    }
}

运行结果如下:

像以上情况,一边遍历的时候去删除数据,直接会报错,原因是因为集合是一个可变的容器,每删一个数据,容器的大小都会改变,那么数据存放的位置也会相应的改变。迭代器遍历可能不好理解,我们就换成普通的 for 循环,但是两者的出现的 Bug 是一样的。

代码如下:

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class Text_For {
    public static void main(String[] args) {
        //创建对象,再添加数据
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("陈七");
        list.add("李麻子");
        list.add("李四");
        list.add("王五");

        for (int i = 0; i < list.size(); i++) {
            String a = list.get(i);
            if (a.contains("李")){
                list.remove(a);
            }
        }
        System.out.println(list);
    }
}

运行结果如下:

发现用 for 循环竟然不报错,原因可能是没有用迭代器遍历严谨吧,以上的两种代码的效果都是一样的,会出现 Bug ,就是本来要删除带 "李" 的名字,但是发现名字还有一个"李四",没有被删除,那是什么原因呢?

直接会把 "李四" 忽略掉,这就是这出现 Bug 的地方。

1.1 如何解决集合的并发修改问题

对于用普通的 for 循环来遍历的代码来说可以有两种方法;第一个方法就是每一次删除数据的时候,都要进行 i--; 第二方法就是从尾开始遍历。

代码如下:

第一种方法

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class Text_For {
    public static void main(String[] args) {
        //创建对象,再添加数据
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("陈七");
        list.add("李麻子");
        list.add("李四");
        list.add("王五");

        for (int i = 0; i < list.size(); i++) {
            String a = list.get(i);
            if (a.contains("李")){
                list.remove(a);
                i--;
            }
        }
        System.out.println(list);
    }
}

运行结果如下:

成功把"李四"也删除掉了。

第二种方法

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class Text_For {

    public static void main(String[] args) {
        //创建对象,再添加数据
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("陈七");
        list.add("李麻子");
        list.add("李四");
        list.add("王五");

        for (int i = list.size() - 1; i >= 0; i--) {
            String a = list.get(i);
            if (a.contains("李")){
                list.remove(a);
            }
        }
        System.out.println(list);
    }
}

运行结果如下:

一样也可以把"李四"删除掉。

对于用迭代器来遍历的代码来说,只能把集合对象.remove(String str) 换成迭代器对象.remove() 。

代码如下:

java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Abnormal {
    public static void main(String[] args) {

        //创建对象,再添加数据
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("陈七");
        list.add("李麻子");
        list.add("李四");
        list.add("王五");
        //利用迭代器进行遍历,先创建迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String a = iterator.next();
            if (a.contains("李")){
                iterator.remove();
            }
        }
        System.out.println(list);
    }
}

运行结果如下:

也是可以的。

对于增强 for 循环还有利用 Lambda 表达式的循环都不可以用来一边遍历集合,一边删除数据,无法解决集合的并发修改异常。

2.0 Collcetions 工具类的说明

是一个用来操作集合的工具类。

以代码为例来介绍具体的静态方法:

java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Text_Collections {
    public static void main(String[] args) {
        String s1 = "李四";
        String s2 = "张三";
        String s3 = "王五";
        String s4 = "张麻子";
        List<String> list = new ArrayList<>();

        //1. addAll() 为集合批量添加数据
        Collections.addAll(list,s1,s2,s3,s4);
        System.out.println(list);
        //输出结果为:[李四, 张三, 王五, 张麻子]

        //2. shuffle() 打乱list集合中的元素顺序
        Collections.shuffle(list);
        System.out.println(list);
        //输出结果为:[王五, 张麻子, 李四, 张三]

        //3. sort() 对list集合的元素进行升序排序
        Collections.sort(list);
        System.out.println(list);
        //输出结果为:[张三, 张麻子, 李四, 王五]

    }
}

运行结果如下:

补充第三种方法,如果对自定的对象进行排序的话,默认的 sort 是会报错的,所以得自定义比较,创建一个比较器。

代码如下:

java 复制代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Text_Collections {
    public static void main(String[] args) {
        Student s1 = new Student("张三",19);
        Student s2 = new Student("李四",33);
        Student s3 = new Student("王五",21);

        List<Student> list = new ArrayList<>();
        Collections.addAll(list,s1,s2,s3);
        //自定义,根据年龄进行排序
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge()- o2.getAge();
            }
        });
        System.out.println(list);
    }
}

运行结果如下:



相关推荐
王哈哈嘻嘻噜噜5 分钟前
c语言中“函数指针”
java·c语言·数据结构
神奇夜光杯12 分钟前
Python酷库之旅-第三方库Pandas(123)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
qq_3391911413 分钟前
spring boot admin集成,springboot2.x集成监控
java·前端·spring boot
zhangbin_23719 分钟前
【Python机器学习】NLP信息提取——提取人物/事物关系
开发语言·人工智能·python·机器学习·自然语言处理
_.Switch29 分钟前
构建现代应用的Python Serverless架构详解
运维·开发语言·python·云原生·架构·serverless·restful
苹果酱056729 分钟前
通过springcloud gateway优雅的进行springcloud oauth2认证和权限控制
java·开发语言·spring boot·后端·中间件
offduty32 分钟前
Python基础03 | 变量和函数
python
Sunny_yiyi32 分钟前
Gateway--服务网关
java·开发语言·gateway
空城皆是旧梦38 分钟前
python爬虫初体验(二)
爬虫·python
crownyouyou41 分钟前
第一次安装Pytorch
人工智能·pytorch·python