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


    目录

            1.0 集合的并发修改问题

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

            2.0 Collcetions 工具类的说明


            1.0 集合的并发修改问题

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

    代码如下:

    1. import java.util.ArrayList;
    2. import java.util.Iterator;
    3. import java.util.List;
    4. public class Abnormal {
    5. public static void main(String[] args) {
    6. //创建对象,再添加数据
    7. List list = new ArrayList<>();
    8. list.add("张三");
    9. list.add("陈七");
    10. list.add("李麻子");
    11. list.add("李四");
    12. list.add("王五");
    13. //利用迭代器进行遍历,先创建迭代器
    14. Iterator iterator = list.iterator();
    15. while (iterator.hasNext()){
    16. String a = iterator.next();
    17. if (a.contains("李")){
    18. list.remove(a);
    19. }
    20. }
    21. System.out.println(list);
    22. }
    23. }

    运行结果如下:

           

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

    代码如下:

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class Text_For {
    4. public static void main(String[] args) {
    5. //创建对象,再添加数据
    6. List list = new ArrayList<>();
    7. list.add("张三");
    8. list.add("陈七");
    9. list.add("李麻子");
    10. list.add("李四");
    11. list.add("王五");
    12. for (int i = 0; i < list.size(); i++) {
    13. String a = list.get(i);
    14. if (a.contains("李")){
    15. list.remove(a);
    16. }
    17. }
    18. System.out.println(list);
    19. }
    20. }

    运行结果如下:

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

            

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

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

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

    代码如下:

    第一种方法

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class Text_For {
    4. public static void main(String[] args) {
    5. //创建对象,再添加数据
    6. List list = new ArrayList<>();
    7. list.add("张三");
    8. list.add("陈七");
    9. list.add("李麻子");
    10. list.add("李四");
    11. list.add("王五");
    12. for (int i = 0; i < list.size(); i++) {
    13. String a = list.get(i);
    14. if (a.contains("李")){
    15. list.remove(a);
    16. i--;
    17. }
    18. }
    19. System.out.println(list);
    20. }
    21. }

    运行结果如下:

            成功把”李四“也删除掉了。

    第二种方法

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. public class Text_For {
    4. public static void main(String[] args) {
    5. //创建对象,再添加数据
    6. List list = new ArrayList<>();
    7. list.add("张三");
    8. list.add("陈七");
    9. list.add("李麻子");
    10. list.add("李四");
    11. list.add("王五");
    12. for (int i = list.size() - 1; i >= 0; i--) {
    13. String a = list.get(i);
    14. if (a.contains("李")){
    15. list.remove(a);
    16. }
    17. }
    18. System.out.println(list);
    19. }
    20. }

    运行结果如下:

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

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

    代码如下:

    1. import java.util.ArrayList;
    2. import java.util.Iterator;
    3. import java.util.List;
    4. public class Abnormal {
    5. public static void main(String[] args) {
    6. //创建对象,再添加数据
    7. List list = new ArrayList<>();
    8. list.add("张三");
    9. list.add("陈七");
    10. list.add("李麻子");
    11. list.add("李四");
    12. list.add("王五");
    13. //利用迭代器进行遍历,先创建迭代器
    14. Iterator iterator = list.iterator();
    15. while (iterator.hasNext()){
    16. String a = iterator.next();
    17. if (a.contains("李")){
    18. iterator.remove();
    19. }
    20. }
    21. System.out.println(list);
    22. }
    23. }

    运行结果如下:

            也是可以的。

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

            2.0 Collcetions 工具类的说明

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

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

    1. import java.util.ArrayList;
    2. import java.util.Collections;
    3. import java.util.List;
    4. public class Text_Collections {
    5. public static void main(String[] args) {
    6. String s1 = "李四";
    7. String s2 = "张三";
    8. String s3 = "王五";
    9. String s4 = "张麻子";
    10. List list = new ArrayList<>();
    11. //1. addAll() 为集合批量添加数据
    12. Collections.addAll(list,s1,s2,s3,s4);
    13. System.out.println(list);
    14. //输出结果为:[李四, 张三, 王五, 张麻子]
    15. //2. shuffle() 打乱list集合中的元素顺序
    16. Collections.shuffle(list);
    17. System.out.println(list);
    18. //输出结果为:[王五, 张麻子, 李四, 张三]
    19. //3. sort() 对list集合的元素进行升序排序
    20. Collections.sort(list);
    21. System.out.println(list);
    22. //输出结果为:[张三, 张麻子, 李四, 王五]
    23. }
    24. }

    运行结果如下:

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

    代码如下:

    1. import java.util.ArrayList;
    2. import java.util.Collections;
    3. import java.util.Comparator;
    4. import java.util.List;
    5. public class Text_Collections {
    6. public static void main(String[] args) {
    7. Student s1 = new Student("张三",19);
    8. Student s2 = new Student("李四",33);
    9. Student s3 = new Student("王五",21);
    10. List list = new ArrayList<>();
    11. Collections.addAll(list,s1,s2,s3);
    12. //自定义,根据年龄进行排序
    13. Collections.sort(list, new Comparator() {
    14. @Override
    15. public int compare(Student o1, Student o2) {
    16. return o1.getAge()- o2.getAge();
    17. }
    18. });
    19. System.out.println(list);
    20. }
    21. }

    运行结果如下:

     



  • 相关阅读:
    Android 按上/下键,焦点会移动到第一个控件上面或最后一个控件下面的解决办法
    【Pytorch】pytorch中保存模型的三种方式
    探秘OpenAI的神奇之作:Sora技术揭秘
    ElasticSearch 常见问题
    全屏展示 【前端实现】
    现代密码学-国密算法
    那些破釜沉舟入局Web3.0的互联网精英都怎么样了?
    【LeetCode】【剑指offer】【在排序数组中查找数字(一)】
    【Composite模式】C++设计模式——组合模式
    关于redisson的序列化配置
  • 原文地址:https://blog.csdn.net/Tingfeng__/article/details/133965478