ArrayList 采坑

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

 List<String> list = new ArrayList<String>();
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.里面维护了两个变量 modcountexpectmodcount
    如果两个数不等,就报错。ArrayList#remove 之后将会使 modCount
    加一
    ,遍历下一个时,expectedModCount与 modCount将会不相等,这就导致迭代器遍历时将会抛错。

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

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

Iteartor<String> 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<String> list = Arrays.asList(array);  //此处返回的是ArrayList?

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

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

  1. 发现这里返回的ArrayList并不是java.utils.ArrayList ,而是Arrays自带的一个内部类 java.utils.Arrays$ArrayList,是李鬼不是李逵!!!
  2. 虽然李鬼也是实现了抽象list类,但是没有重写add、remove等方法。
    在这里插入图片描述
    真正的李逵ArrayList实现了,而李鬼没有,就调用父类的方法直接报错。
  3. 此外,李鬼还有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<String> list = new ArrayList<>(Arrays.asList("one", "two", "three"));
List<String> unmodifiableList = List.of(list.toArray(new String[]{}));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值