傻大方


首页 > 潮·科技 > >

盘点这些年Java 集合类 List 的那些坑



按关键词阅读:

现在的一些高级编程语言都会提供各种开箱即用的数据结构的实现 , 像 Java 编程语言的集合框架中就提供了各种实现 , 集合类包含 Map 和 Collection 两个大类 , 其中 Collection 下面的 List 列表是我们经常使用的集合类之一 , 很多的业务代码都离不开它 , 今天就来看看 List 列表的一些坑 。
第一个坑:Arrays.asList 方法返回的 List 不支持增加、删除操作例如我们执行以下代码:
List strings = Arrays.asList("m", "g");strings.add("h");会抛出 java.lang.UnsupportedOperationException 异常 , 此时你内心 OS what?明明返回的 ArrayList 为啥不能往里面增加元素 , 这以后还能好好的增加元素吗? , 然后果断开启 Debug 大法:
盘点这些年Java 集合类 List 的那些坑文章插图
发现返回的 ArrayList 并不是我们常用的 java.util.ArrayList , 而是 Arrays 的内部类 java.util.Arrays.ArrayList 。 进入方法 Arrays.asList 源码如下:
public staticList asList(T... a) {return new ArrayList<>(a);}方法返回的是 Arrays 的静态内部类 java.util.Arrays.ArrayList , 该类虽然和 java.util.ArrayList 也继承自抽象类 java.util.AbstractList, 但是通过该类的源码发现它并没有对抽象父类AbstractList的 add 方法默认就是抛出 java.lang.UnsupportedOperationException 异常 。
盘点这些年Java 集合类 List 的那些坑文章插图
这个坑的根本原因是我们调用返回的 strings 的 add 方法是继承自抽象父类的 add 方法 , 而抽象父类的方法默认就是抛出 java.lang.UnsupportedOperationException 这个异常 。
第二个坑 , Arrays.asList 方法返回的新 List 和该方法原始入参数组修改会相互影响Arrays.asList 方法除了上面这个不支持增加、删除元素这个坑之外 , 还有另外一个坑:
盘点这些年Java 集合类 List 的那些坑文章插图
从以上代码可以发现 , 对原始数组的修改会影响我们通过 Arrays.asList方法获得的新 List , 深入 java.util.Arrays.ArrayList 的源码:
private static class ArrayList extends AbstractListimplements RandomAccess, java.io.Serializable{private static final long serialVersionUID = -2764017481108945198L;private final E[] a;ArrayList(E[] array) {a = Objects.requireNonNull(array);}...}可以发现是直接使用了原始的数组 , 所有当我们使用 Arrays.asList 方式获得的 List 时要特别注意 , 因为共享了数组 , 相互修改时可能产生一些意想不到的 Bug 。 标准的姿势之一是将其作为 ArrayList 构造方法的参数重新 new 一个 List 出来即可(e.g. List stringList = new ArrayList<>(Arrays.asList(arrays)))或者通过 Guava 库中的 Lists.newArrayList, 将返回的新 List 和原始的数组解耦 , 就不会再互相影响了 。
第三个坑 , 直接遍历 List 集合删除元素会报错在直接遍历集合元素时增加、删除元素会报错 , 比如执行如下代码:
List stringList = Lists.newArrayList("m", "g", "h");for (String s : stringList) {if (Arrays.asList("m", "h").contains(s)) {stringList.remove(s);}}以上代码可以正常编译通过 , 但是执行时会抛出 java.util.ConcurrentModificationException 异常 , 查看其源码可以发现 , 删除元素方法 remove 会使集合结构发生修改 , 也就是 modCount(集合实际修改的次数)会修改 , 在循环过程中 , 会比较当前 List 的集合实际修改的次数 modCount 与迭代器修改的次数 expectedModCount, 而 expectedModCount 是初始化时的 modCount ,二者不相等 , 就会报 ConcurrentModificationException 异常 。 解决方法主要有两种方式 , 1.使用 ArrayList 的迭代器方式遍历 , 然后调用其中的方法 。 2.在 JDK 1.8+ 可以使用 removeIf 方法进行删除操作 。
最后扎心一问:调用 ArrayList 的 remove 方法传入 int 基本类型的数字和 Integer 包装类型的数字 , 执行结果是不是一样的?
关注我 , 私信回复【资料】即可领取视频中java相关资料以及一份227页最新的bat大厂面试宝典
最后【盘点这些年Java 集合类 List 的那些坑】欢迎大家一起交流 , 喜欢文章记得关注我点个赞哟 , 感谢支持!


    稿源:(未知)

    【傻大方】网址:http://www.shadafang.com/c/111T320332020.html

    标题:盘点这些年Java 集合类 List 的那些坑


    上一篇:什么?您也想玩小的ATX主机?同道中人啊

    下一篇:深度学习GPU最全对比,到底谁才是性价比之王?