集合踩坑记录
阿里巴巴java开发手册中提到过的几种情况
SubList截取视图
【强制】 ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException 异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList; 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
【强制】 在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException 异常。
For循环中进行add/remove操作
【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator 方式,如果并发操作,需要对Iterator对象加锁。
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
if ("2".equals(item)) {
list.remove(item);
}
}
}
执行比较”1“时正常运行,比较”2“则报错
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.wcb.lambda.TestCollection.main(TestCollection.java:17)
Process finished with exit code 1
Comparator满足自反
Comparator要满足自反性,传递性,对称性,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。
说明:
1) 自反性:x,y的比较结果和y,x的比较结果相反。
2) 传递性:x>y,y>z,则x>z。
3) 对称性:x=y,则x,z比较结果和y,z比较结果相同。反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2){
return o1.getId() > o2.getId() ? 1 :-1;
}
}
Map的线程安全与空值存储
Map 类集合 K/V 能不能存储 null 值的情况,如下表格:
集合类 | Key | Value | Super | 说明 |
---|---|---|---|---|
Hashtable | 不允许为 null | 不允许为 null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为 null | 不允许为 null | AbstractMap | 分段锁技术 |
TreeMap | 不允许为 null | 允许为 null | AbstractMap | 线程不安全 |
HashMap | 允许为 null | 允许为 null | AbstractMap | 线程不安全 |
Arrays工具转集合操作
Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。 asList() 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。
public class TestCollection {
public static void main(String[] args) {
Integer[] arr={1,2,3,4,5};
Arrays.asList(arr).remove(1);
}
}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at com.wcb.lambda.TestCollection.main(TestCollection.java:14)
Process finished with exit code 1
在转换之后,再对数组的值进行修改时,集合也会跟着变化
public class TestCollection {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4, 5};
List<Integer> list= Arrays.asList(arr);
arr[0]=10;
System.out.println(list.toString());
}
}
结果为 [10, 2, 3, 4, 5]