今天就跟大家聊聊有关深入浅析Java中列表集合类的一些问题,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
<强>第一个坑:数组。asList方法返回的列表不支持增加,删除操作强>
例如我们执行以下代码:
List字符串=arrays . aslist (“m",“g"); strings.add (“h");
会抛出<代码> . lang。UnsupportedOperationException> 代码方式异常,此时你内心OS <代码>什么?明明返回的ArrayList为啥不能往里面增加元素,这以后还能好好的增加元素吗?> 代码,然后果断开启<代码> 代码>大调试法:
发现返回的<代码> ArrayList> 代码并不是我们常用的<代码> java.util。ArrayList> 代码,而是<代码> 代码>阵列的内部类<代码> java.util.Arrays。ArrayList> 代码。进入方法<代码>数组。asList> 代码源码如下:
公共静态& lt; T>ListasList (T…一){ 返回新ArrayList<祝辞(a); }
方法返回的是<代码> 代码>阵列的静态内部类<代码> java.util.Arrays。ArrayList> 代码,该类虽然和<代码> java.util。ArrayList> 代码也继承自抽象类<代码> java.util。AbstractList> 代码,但是通过该类的源码发现它并没有对抽象父类<代码> AbstractList 代码>的<代码> 代码>添加方法默认就是抛出<代码> . lang。UnsupportedOperationException> 代码方式异常。
这个坑的根本原因是我们调用返回的字符串<代码> 代码>的<代码> 代码>添加方法是继承自抽象父类的<代码> 代码>添加方法,而抽象父类的方法默认就是抛出<代码> . lang。UnsupportedOperationException> 代码方式这个异常。
<代码>数组。asList 代码>方法除了上面这个<强>不支持增加,删除元素强>这个坑之外,还有另外一个坑:
从以上代码可以发现,对原始数组的修改会影响我们通过<代码>数组。asList 代码>方法获得的新<代码> 代码>列表,深入<代码> java.util.Arrays。ArrayList> 代码的源码:
私有静态类ArrayList扩展AbstractList 实现了RandomAccess, java.io.Serializable { 私有静态最终长serialVersionUID=-2764017481108945198 l; 私人最终E []; ArrayList (E[]数组){ 一个=Objects.requireNonNull(数组); } … }
可以发现是直接使用了原始的数组,所有当我们使用<代码>数组。asList 代码>方式获得的<代码> 代码>列表时要特别注意,因为共享了数组,相互修改时可能产生一些意想不到的错误。标准的姿势之一是将其作为<代码> ArrayList 代码>构造方法的参数重新新的<代码> 代码>一个<代码> 代码>出列表来即可。<代码> List
在直接遍历集合元素时增加,删除元素会报错,比如执行如下代码:
ListstringList=Lists.newArrayList (“m",“g",“h"); (字符串s: stringList) { 如果(arrays . aslist ()“m",“h" .contains (s)) { stringList.remove(年代); } }
以上代码可以正常编译通过,但是执行时会抛出<代码> java.util。ConcurrentModificationException 代码>异常查,看其源码可以发现,删除元素方法<代码>删除> 代码会使集合结构发生修改,也就是<代码> modCount(> 代码集合实际修改的次数)会修改,在循环过程中,会比较当前<代码> >代码列表的集合实际修改的次数<代码> modCount> 代码与迭代器修改的次数<代码> expectedModCount> 代码,而<代码> expectedModCount> 代码是初始化时的<代码> modCount> 代码,二者不相等,就会报代码>,<代码> ConcurrentModificationException异常。解决方法主要有两种方式,1。使用<代码> ArrayList> 代码的迭代器方式遍历,然后调用其中的方法。2。在JDK 1.8 +可以使用<代码> removeIf 代码>方法进行删除操作。