Java Arrays、ArrayList相关坑
Arrays坑
循环遍历问题
对数据做循环遍历的时候,不能直接remove、add 操作,否则会报异常
List<Integer> list = Arrays.asList(1, 2, 3, 4);
for (Integer i : list) {
System.out.println(i);
list.remove(1);
}
AsList()坑
- AsList 返回值不支持操作问题,否则会报异常
List<Integer> list = Arrays.asList(1, 2, 3, 4);
for (Integer i : list) {
System.out.println(i);
list.remove(1);
}
list.add(5)
报错UnsupportedOperationException的原因是
public static <T> List<T> asList(T... a) {
//返回值是内部ArrayList
return new ArrayList<>(a);
}
//该类未覆盖实现add、remove等操作,默认采用AbstractList,
//而AbstractList类add、remove等方法会默认抛出UnsupportedOperationException异常
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable {
.........
}
- 对原始数组的修改会影响到我们获得的那个 List
Integer[] a = {1, 2};
List<Integer> list = Arrays.asList(a);
for (Integer i : list) {
System.out.println("未修改数组前数据:" + i);
}
System.out.println("---------------------");
a[0] = 6;
a[1] =8;
for (Integer i : list) {
System.out.println("修改数组后数据:" + i);
}
结果输出如下:
未修改数组前数据:1
未修改数组前数据:2
修改数组后数据:6
修改数组后数据:8
出现这个原因还和Arrays内部类ArrayList 有关系,通过内部代码发现创建ArrayList时,只是把引用传递给ArrayList类的成员变量a中。
调整该报错也很简单,就是不要把要传递的数组复制一遍,然后再传递给AsList函数。
ArrayList坑
- 对数据做循环遍历的时候,不能直接remove、add 操作,否则会报异常
Integer[] a = {1, 2};
List<Integer> list = new ArrayList<>(Arrays.asList(a));
for (Integer i : list) {
System.out.println("未修改数组前数据:" + i);
list.add(4);
}
- 使用不当 List.subList 可能会导致 OOM
业务开发时常常要对 List 做切片处理,即取出其中部分元素构成一个新的 List,我们通常会想到使用 List.subList 方法。但,和 Arrays.asList 的问题类似,List.subList 返回的子 List 不是一个普通的 ArrayList。这个子 List 可以认为是原始 List 的视图,会和原始 List 相互影响。如果不注意,很可能会因此产生 OOM 问题。
private static List<List<Integer>> data = new ArrayList<>();
private static void oom() {
for (int i = 0; i < 1000; i++) {
List<Integer> rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());
data.add(rawList.subList(0, 1));
}
}
总结
大家在使用ArrayList和Arrays有遇到哪些坑,欢迎大家补充。