Java-ArrayList使用注意
使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方
法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适
配器模式,只是转换接口,后台的数据仍是数组。
String[] str = new String[] { “yang”, “hao” };
List list = Arrays.asList(str);
第一种情况:list.add(“yangguanbao”); 运行时异常。
第二种情况:str[0] = “changed”; 也会随之修改,反之亦然。
使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
往列表里面新增数据
String[] str = new String[] { "apple", "grapes" };
List list = Arrays.asList(str);
System.out.println(list);
list.add("banana");
结果
[apple, grapes]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at LearnArrayList.main(LearnArrayList.java:22)
Process finished with exit code 1
更改原数组的值
String[] str = new String[]{"apple", "grapes"};
List list = Arrays.asList(str);
System.out.println(list);
str[0] = "banana";
System.out.println(list);
结果
[apple, grapes]
[banana, grapes]
原因
Arrays.asList返回的并不是我们常用的ArrayList,而是
Arrays
类的内部类AbstractList
类,重写了很多方法,比如我们上面使用的contains
方法,但是却没有重写add
方法,所以我们在调用add
方法时才会抛出java.lang.UnsupportedOperationException
异常。
subList用于返回原集合的子集
示例
List<String> carList = new ArrayList<>();
carList.add("奥迪");
carList.add("宝马");
carList.add("奔驰");
carList.add("保时捷");
carList.add("马萨拉蒂");
System.out.println(carList);
List<String> myCarList=carList.subList(2,3);
System.out.println(myCarList);
List<String> otherCarList=carList.subList(3,3);
System.out.println(otherCarList);
[奥迪, 宝马, 奔驰, 保时捷, 马萨拉蒂]
[奔驰]
[]
注意,subList的定义如下
List subList(int fromIndex, int toIndex);
fromIndex, inclusive, and toIndex, exclusive. (IffromIndex and toIndex are equal, the returned list isempty.)subList(a,b) 返回的是包含a但是不包含b的子集,如果a=b,则返回空集
子集使用
-
修改原集合元素的值,会影响子集合
示例
List<String> carList = new ArrayList<>(); carList.add("奥迪"); carList.add("宝马"); carList.add("奔驰"); carList.add("保时捷"); carList.add("马萨拉蒂"); System.out.println(carList); List<String> myCarList=carList.subList(2,3); System.out.println(myCarList); carList.set(2,"五菱"); System.out.println(myCarList);
结果
[奥迪, 宝马, 奔驰, 保时捷, 马萨拉蒂] [奔驰] [五菱]
-
修改原集合的结构,会引起
ConcurrentModificationException
异常【强制】在 subList 场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。
示例
List<String> carList = new ArrayList<>(); carList.add("奥迪"); carList.add("宝马"); carList.add("奔驰"); carList.add("保时捷"); carList.add("马萨拉蒂"); System.out.println(carList); List<String> myCarList=carList.subList(2,3); System.out.println(myCarList); carList.add("别克"); System.out.println(myCarList);//修改结构后导致遍历异常
结果
[奥迪, 宝马, 奔驰, 保时捷, 马萨拉蒂] [奔驰] Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239) at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099) at java.util.AbstractList.listIterator(AbstractList.java:299) at java.util.ArrayList$SubList.iterator(ArrayList.java:1095) at java.util.AbstractCollection.toString(AbstractCollection.java:454) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at LearnArrayList.main(LearnArrayList.java:52)
-
修改子集合元素的值,会影响原集合
示例
List<String> carList = new ArrayList<>(); carList.add("奥迪"); carList.add("宝马"); carList.add("奔驰"); carList.add("保时捷"); carList.add("马萨拉蒂"); System.out.println(carList); List<String> myCarList=carList.subList(2,3); System.out.println(myCarList); myCarList.set(0,"长安"); System.out.println(carList);
结果
[奥迪, 宝马, 奔驰, 保时捷, 马萨拉蒂] [奔驰] [奥迪, 宝马, 长安, 保时捷, 马萨拉蒂]
-
修改子集合的结构,会影响原集合
注意这里的顺序是往子集结尾的地方插入
示例
List<String> carList = new ArrayList<>(); carList.add("奥迪"); carList.add("宝马"); carList.add("奔驰"); carList.add("保时捷"); carList.add("马萨拉蒂"); System.out.println(carList); List<String> myCarList=carList.subList(2,3); System.out.println(myCarList); myCarList.add("比亚迪"); System.out.println(carList);
结果
[奥迪, 宝马, 奔驰, 保时捷, 马萨拉蒂] [奔驰] [奥迪, 宝马, 奔驰, 比亚迪, 保时捷, 马萨拉蒂]
总结
ArrayList的subList方法,返回的是原集合的一个子集合(视图),非结构性修改任意一个集合的元素的值,都会彼此影响,结构性修改原集合时,会报
ConcurrentModificationException
异常,结构性修改子集合时,会影响原集合,所以使用时要注意,避免程序错误或者异常。