跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

记录Java 集合类 List 的坑

java基础教程 栏目介绍集合类包含 map 和 collection 两个大类 推荐(免费):java基础教程 现在的一些高级编程语言都会提供各种开箱即用的数据结构的实现,像 Java 编程语言的集合框架中就提供了各种实现,集合类包含 Map 和 Collection 两个大类,其中 Collection 下面的 List 列表是我们经常使用的集合类之一,很多的业务代码都离不开它,今天就来看看 List 列表的一些坑。 第一个坑:Arrays.asList 方法返回的 List 不支持增加、删除操作 例如我们执行以下代码: 立即学习 “ Java免费学习笔记(深入) ”;
List strings = Arrays.asList("m", "g"); strings.add("h");
会抛出
java.lang.UnsupportedOperationException
异常,此时你内心 OS
what?明明返回的 ArrayList 为啥不能往里面增加元素,这以后还能好好的增加元素吗?
,然后果断开启
Debug
大法: 发现返回的
ArrayList
并不是我们常用的
java.util.ArrayList
,而是
Arrays
的内部类
java.util.Arrays.ArrayList
。进入方法
Arrays.asList
源码如下:
public static List asList(T... a) { return new ArrayList<>(a); }
方法返回的是
Arrays
的静态内部类
java.util.Arrays.ArrayList
,该类虽然和
java.util.ArrayList
也继承自抽象类
java.util.AbstractList
,但是通过该类的源码发现它并没有对抽象父类
AbstractList
的
add
方法默认就是抛出
java.lang.UnsupportedOperationException
异常。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 这个坑的根本原因是我们调用返回的
strings
的
add
方法是继承自抽象父类的
add
方法,而抽象父类的方法默认就是抛出
java.lang.UnsupportedOperationException
这个异常。 第二个坑,Arrays.asList 方法返回的新 List 和该方法原始入参数组修改会相互影响
Arrays.asList
方法除了上面这个 不支持增加、删除元素 这个坑之外,还有另外一个坑: 从以上代码可以发现,对原始数组的修改会影响我们通过
Arrays.asList
方法获得的新
List
,深入
java.util.Arrays.ArrayList
的源码:
private static class ArrayList extends AbstractList implements 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
包装类型的数字,执行结果是不是一样的?

相关文章