乐趣区

关于java:List的toArray方法和toArrayT-a方法

这两个办法都是将列表 List 中的元素转导出为数组,不同的是,toArray()办法导出的是 Object 类型数组,而 toArray[T[] a]办法导出的是指定类型的数组。

1. toArray()办法

toArray()办法会返回 List 中所有元素形成的数组,并且数组类型是 Object[]。还要留神一点就是,toArray()返回的是一个新的数组对象,并且屡次执行 toArray()办法取得的是不同的数组对象,并且对其中一个数组进行批改,不会影响到其余 toArray()办法取得的数组,并且也不会影响到 list 自身原来存储的元素值.

private static class People{
    String name;
    public People(String name){this.name = name;}

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                '}';
    }
}

//People 类和上一个例子中的一样,这里不再列出了。public static void main(String[] args) {List<People> list = new ArrayList<>();
    list.add(new People("小明"));
    list.add(new People("小王"));
    Object[] objects1 = list.toArray();
    Object[] objects2 = list.toArray();
    System.out.println("objects1 == objects2 :"+(objects1 == objects2));
    ((People)objects1[1]).name = "小花";
    System.out.println("show objects1:"+ Arrays.toString(objects1));
    System.out.println("show objects2:"+ Arrays.toString(objects2));
    System.out.println("show list:"+list);
}

输入后果:

objects1 == objects2 : false
show objects1: [People{name=‘小明’}, People{name=‘小花’}]
show objects2: [People{name=‘小明’}, People{name=‘小花’}]
show list: [People{name=‘小明’}, People{name=‘小花’}]

从这个例子的输入后果能够看出,对元素对象自身就行批改,会导致 toArray()返回的所有数组中的内容都产生扭转,包含原始的 list 容器外面的元素类容。从这个例子能够得出,如果 list.toArray()返回的数组中寄存的是 list 原始对象的援用,只是创立了一个新的数组来装这些援用,并没有对 list 中原始对象进行拷贝或复制。
ArrayList 中 toArray()的实现源码:

public Object[] toArray() {return Arrays.copyOf(elementData, size);
}

在 ArrayList 中的实现是调用了 Arrays 工具类的 copyOf()办法,这和 ArrayLIst 类中元素的存储构造相干。至于 Arrays.copyOf()办法的作用就是下面剖析的 List 的 toArray()办法的作用了,因为 toArray()实质上就是间接调用的 Arrays.copyOf()办法了。

2、toArray[T[] a]办法

toArray(T[] a)办法应用了泛型参数,能够返回指定类型数组,然而这个泛型在确定的时候必须是 list 中元素类型的父类或自身,至于那个参数数组,其实就是为了传递参数类型罢了
底层源码:

@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

从实现源码中看出,首先会判断数组 a 的长度和 list 元素的个数,进行一个比拟,如果 a 数组的长度小于 list 元素个数,那么就会间接调用工具类 Arrays.copyOf()办法间接进行一个拷贝,留神,这儿的是 Arrays.copyOf(elementData, size, a.getClass())办法,是由元素类型参数的,就是最初一项参数,和 toArray()办法实现 Arrays.copyOf(elementData, size)不雷同。

接着在看,如果数组 a 的长度 length 不小于 list 元素个数,即 a . l e n g t h > = s i z e a.length >= sizea.length>=size 得话,就会走上面的流程,首先调用 System.arraycopy(elementData, 0, a, 0, size)将 ArrayList 里的元素数组 elementData 中的元素拷贝到 a 对象中,至于这个 System.arraycopy()在这里就不具体说了。

接下来会判断一下 a.length 是否大于 list 元素个数 size,如果大于的话,会在 a[size]地位设置一个 null,这个设置的目标是了 toArray(T[] a)办法调用者从返回的数组中检测到 null 时就晓得前面曾经没有 list 元素对象了。

总结

List 接口的 toArray()办法就是间接调用 Arrays.copyOf(elementData, size),将 list 中的元素对象的援用装在一个新的生成数组中。

List 接口的 toArray(T[] a)办法会返回指定类型(必须为 list 元素类型的父类或自身)的数组对象,如果 a.length 小于 list 元素个数就间接调用 Arrays 的 copyOf()办法进行拷贝并且返回新数组对象,新数组中也是装的 list 元素对象的援用,否则先调用 System.arraycopy()将 list 元素对象的援用装在 a 数组中,如果 a 数组还有残余的空间,则在 a[size]搁置一个 null,size 就是 list 中元素的个数,这个 null 值能够使得 toArray(T[] a)办法调用者能够判断 null 前面曾经没有 list 元素了。

退出移动版