栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ArrayList 采坑

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ArrayList 采坑

记录一下看到的关于ArrayList的面经
1. ArrayList迭代过程删除问题:

 List list = new ArrayList();
2         list.add("1");
3         list.add("2");
		  list.add("3");
4         for (String item : list) {
5             System.out.println("item:" + item);
6             if ("1".equals(item)) {
7                 list.remove(item); // java.util.ConcurrentModificationException 修改时异常
8             }

			  if ("2".equals(item)) {
7                 list.remove(item); // 无报错
8             }  

使用foreach是容易报修改时异常的原因分析:当使用ArrayList.foreach 遍历时,其实会编译成迭代器
Iterator.里面维护了两个变量 modcount 和 expectmodcount
如果两个数不等,就报错。ArrayList#remove 之后将会使 modCount
加一,遍历下一个时,expectedModCount与 modCount将会不相等,这就导致迭代器遍历时将会抛错。

不会报错的情况:所以只要满足条件:删除的元素在循环时的指针cursor+1=size就会出现这种情况!删除ArrayList倒数第二个(即第
size - 1个元素)就会出现不抛异常的假象。因为此时size ==
cursor,相当于循环退出了。(例如size=3,删除第2个元素;size=4,删除第3个元素)

解决方法:使用安全的集合 copyonWriteList; 或者是直接用迭代器删除

Iteartor iterator = list.Itreator();
while(iterator.hasNext()){
	String a = iterator.Next();
	if("1".equals(a)){
		iterator.remove();
	}
}

第二种方法: list.removeIf(str->(){str.equals("1");})

2. 李逵还是李鬼???

String[] array = {"a","b","c"};
ArrayList list = Arrays.asList(array);  //此处返回的是ArrayList?

调用一下add
list.add("d"); // 报错了 UnsupportedOperationException。

再看一下Arrays.asList()的源码:

    发现这里返回的ArrayList并不是java.utils.ArrayList ,而是Arrays自带的一个内部类 java.utils.Arrays$ArrayList,是李鬼不是李逵!!!虽然李鬼也是实现了抽象list类,但是没有重写add、remove等方法。

    真正的李逵ArrayList实现了,而李鬼没有,就调用父类的方法直接报错。此外,李鬼还有bug,他和那个array数组是共享一个底层list,

    结果:
    arrays:[modify_1, modify_2, 3]
    list:[modify_1, modify_2, 3]
    从日志输出可以看到,不管我们是修改原数组,还是新 List 集合,两者都会互相影响。

    为了避免这个bug,可以套个娃 :ArrayList list = new ArrayList(Arrays.asList(array));

3. List 切片 sublist:subList 生成新集合也会与原始 List 互相影响。

integerList:[10, 20, 3]
subList:[10, 20]

可以发现这个 SubList 内部有一个 parent 字段保存保存最原始 List 。所有外部读写动作看起来是在操作 SubList ,实际上底层动作却都发生在原始 List 中

4. 不可变集合的漏洞
上面最后三行写操作都将会抛出 UnsupportedOperationException 异常,但是如果对list操作,照样可以修改。原因和问题三一样,list和unmodifiableList底层是同一个list

解决方法:
使用 JDK9 List#of 方法。

List list = new ArrayList<>(Arrays.asList("one", "two", "three"));
List unmodifiableList = List.of(list.toArray(new String[]{}));
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/715815.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号