欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-13 22:53:30
...

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);

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