美文网首页java-spring
Java List转数组几种方式性能问题

Java List转数组几种方式性能问题

作者: sd_1962 | 来源:发表于2019-12-26 23:04 被阅读0次

    List集合使用toArray方法转成数组,该方法重载了两种形式,无参的和有参的,有参的又可以指定目的数组的不同长度,根据数组长度和原有List元素个数(size)的比较又可以分为几种情况,每一种方式对性能的影响不一。本文主要以实例结合源码来分析不同情况性能问题,供实际工作和面试时参考。不多说,直接上干货

    创建一个简单的List,插入3个元素

    List<String> list1 = new ArrayList<>();
            list1.add("a");
            list1.add("b");
            list1.add("c");
    

    方式1:使用无参toArray方法

    Object[] arr1 = list1.toArray();
    System.out.println("遍历arr1");
    for (Object object : arr1) {
                //可能会有类型转换错误
                Integer i1 = (Integer)object;
                System.out.println(i1);
                
                System.out.println(object);
        }
    

    该方式只能转成Object类型数组,原有集合指定的泛型消失,相当于类型擦除
    隐患:如果拆箱时强转成其他类型,可能会出现ClassCastException,比如代码中的
    Integer i1=(Integer)object 而且这种问题编译时不能识别,把问题隐藏到运行时

    方式2:使用有参toArray方法

     public <T> T[] toArray(T[] a) {
    

    ** 该重载形式可以返回同List对应的泛型数组,保留了元素类型信息,避免了方式1的ClassCastException隐患

    方式2.1 目的数组长度大于 0小于原List的 size

        
            String[] arr3 = new String[2];
            //长度不够,需要复制一个新数组
            arr3 = list1.toArray(arr3);
            
            System.out.println("遍历arr3");
            for (String string : arr3) {
                System.out.println(string);
            }
            
    

    ** 由于数组长度小于List长度,为了能把集合中的元素放入数组,这种方式会重新创建大小等于 size 的数组(复制一个长度为size的新数组),频繁操作会增加 GC 负担。其对应源码为:**

    if (a.length < size)
       return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    

    方式2.2 目的数组长度大于 0大于原List的 size

        
            String[] arr4 = new String[5];
            //目的数组长度大于原List长度
            list1.toArray(arr4);
            
            System.out.println("遍历arr4");
            for (String string : arr4) {
                System.out.println(string);
            }
            
    

    由于数组长度小于List长度,一方面浪费空间,另一方面List size 对应的位置只能插入 null 值,存在 Null指针异常 隐患。其对应源码为:

    
     if (a.length > size)
        a[size] = null;
    

    方式2.3 目的数组长度等于 0,动态创建与原List size 相同长度的数组

        
        String[] arr2 = list1.toArray(new String[0]);
        System.out.println("遍历arr2");
            for (String string : arr2) {
                System.out.println(string);
            }
            
    

    不多不少,直接挨个复制,这是性能最好的方式。其对应源码为:

    System.arraycopy(elementData, 0, a, 0, size);
    

    结语:即便是很常见,看起来很简单的集合操作,不同的实现方式也会有细微的差别,并且可能在生产环境中会对性能产生不小的影响

    相关文章

      网友评论

        本文标题:Java List转数组几种方式性能问题

        本文链接:https://www.haomeiwen.com/subject/yjcroctx.html