首页后端开发其他后端知识聊聊Java List集合类的应用,这些坑你踩过吗?

聊聊Java List集合类的应用,这些坑你踩过吗?

时间2024-03-28 15:50:03发布访客分类其他后端知识浏览1409
导读:这篇文章给大家分享的是Java List集合类的相关内容,Java 编程语言的集合框架中就提供了各种实现,集合类包含 Map 和 Collection 两个大类,其中 Collection 下面的 List 列表是我们经常使用的集合类之一。...

这篇文章给大家分享的是Java List集合类的相关内容,Java 编程语言的集合框架中就提供了各种实现,集合类包含 Map 和 Collection 两个大类,其中 Collection 下面的 List 列表是我们经常使用的集合类之一。接下来主要是给大家介绍一下使用List 列表的一些坑,对大家学习有一定的参考价值,感兴趣的就继续往下看吧。

现在的一些高级编程语言都会提供各种开箱即用的数据结构的实现,像 ,很多的业务代码都离不开它,今天就来看看 List 列表的一些坑。

第一个坑:Arrays.asList 方法返回的 List 不支持增加、删除操作

例如我们执行以下代码:

ListString>
     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 T>
     ListT>
 asList(T... a) {
    
    return new ArrayList>
    (a);

}
    

方法返回的是 Arrays 的静态内部类 java.util.Arrays.ArrayList,该类虽然和 java.util.ArrayList 也继承自抽象类 java.util.AbstractList ,但是通过该类的源码发现它并没有对抽象父类AbstractListadd 方法默认就是抛出 java.lang.UnsupportedOperationException 异常。

这个坑的根本原因是我们调用返回的 stringsadd 方法是继承自抽象父类的 add 方法,而抽象父类的方法默认就是抛出 java.lang.UnsupportedOperationException 这个异常。

第二个坑,Arrays.asList 方法返回的新 List 和该方法原始入参数组修改会相互影响

Arrays.asList 方法除了上面这个 不支持增加、删除元素 这个坑之外,还有另外一个坑:

从以上代码可以发现,对原始数组的修改会影响我们通过 Arrays.asList方法获得的新 List,深入 java.util.Arrays.ArrayList 的源码:

private static class ArrayListE>
     extends AbstractListE>

        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. ListString> stringList = new ArrayList> (Arrays.asList(arrays)))或者通过 Guava 库中的 Lists.newArrayList ,将返回的新 List 和原始的数组解耦,就不会再互相影响了。

第三个坑,直接遍历 List 集合删除元素会报错

在直接遍历集合元素时增加、删除元素会报错,比如执行如下代码:

ListString>
     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 方法进行删除操作。

最后扎心一问:调用 ArrayListremove 方法传入 int 基本类型的数字和 Integer 包装类型的数字,执行结果是不是一样的?

关于Java List集合类的内容就介绍到这,希望大家阅读完这篇文章能有所收获。最后,想要了解更多大家可以关注网络其它相关文章。

文本转载自PHP中文网

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 聊聊Java List集合类的应用,这些坑你踩过吗?
本文地址: https://pptw.com/jishu/655040.html
用JS怎么做线性表表示链式 Java封装和继承不理解?两个案例帮到你

游客 回复需填写必要信息