目录
1.0 集合的并发修改问题
1.1 如何解决集合的并发修改问题
2.0 Collcetions 工具类的说明
1.0 集合的并发修改问题
我们可以简单的认为,就是使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
代码如下:
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 是一样的。
代码如下:
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--; 第二方法就是从尾开始遍历。
代码如下:
第一种方法
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); } }
运行结果如下:
成功把”李四“也删除掉了。
第二种方法
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() 。
代码如下:
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 工具类的说明
是一个用来操作集合的工具类。
以代码为例来介绍具体的静态方法:
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 是会报错的,所以得自定义比较,创建一个比较器。
代码如下:
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); } }
运行结果如下: