美文网首页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