ArrayList(Collection extends E> collection)方法里面为什么是复制了两次?

时间:2022-06-13 17:03:11
 public ArrayList(Collection<? extends E> collection) {
        if (collection == null) {
            throw new NullPointerException("collection == null");
        }

        Object[] a = collection.toArray();
        if (a.getClass() != Object[].class) {
            Object[] newArray = new Object[a.length];
            System.arraycopy(a, 0, newArray, 0, a.length);
            a = newArray;
        }
        array = a;
        size = a.length;
    }


这里的a.getClass()!=Object[].class是什么意思?还有就是问什么要把把a先拷贝到newArray在把newArray拷贝到然后在赋值给array,为什么不直接赋给呢?如果是怕a影响到传来的collection的值,那具体是怎么影响的呢?

5 个解决方案

#1


1, 确保array 里面全部的元素都统一是Object类
2, 确保这个ArrayList 不会因为传入的集合因为外部的改动而改动

#2


比如 一个Set  s有 A, B,C
ArrayList a = new ArrayList(s);

如果直接赋值,当s删减或者增加元素的时候,a 也会受影响

#3


该回复于2017-01-10 13:44:53被管理员删除

#4


拷贝的问题楼上已经有人讲了,我就不说了,我说下a.getClass()!=Object[].class,这个是因为toArray()的实现方式不同,ArrayList的toArray返回的是Object[],而其他的就可能不是,例如Arrays.asList("1").toArrary()这个返回的是String[],人家源码中的注释已经说明了,我粘过来你看下:

/**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

#5


引用 2 楼 soton_dolphin 的回复:
比如 一个Set  s有 A, B,C
ArrayList a = new ArrayList(s);

如果直接赋值,当s删减或者增加元素的时候,a 也会受影响


引用 4 楼 bigbaldy 的回复:
拷贝的问题楼上已经有人讲了,我就不说了,我说下a.getClass()!=Object[].class,这个是因为toArray()的实现方式不同,ArrayList的toArray返回的是Object[],而其他的就可能不是,例如Arrays.asList("1").toArrary()这个返回的是String[],人家源码中的注释已经说明了,我粘过来你看下:

/**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

我明白了你的意思,但是我还是不懂为什么要判断这个,判断这个有什么意义呢?比如像你说的String[]不满足 ,那么就可以直接把此时的collection转换的集合直接赋值给array?这样直接操作ArrayList肯定会对collection造成影响啊。

#1


1, 确保array 里面全部的元素都统一是Object类
2, 确保这个ArrayList 不会因为传入的集合因为外部的改动而改动

#2


比如 一个Set  s有 A, B,C
ArrayList a = new ArrayList(s);

如果直接赋值,当s删减或者增加元素的时候,a 也会受影响

#3


该回复于2017-01-10 13:44:53被管理员删除

#4


拷贝的问题楼上已经有人讲了,我就不说了,我说下a.getClass()!=Object[].class,这个是因为toArray()的实现方式不同,ArrayList的toArray返回的是Object[],而其他的就可能不是,例如Arrays.asList("1").toArrary()这个返回的是String[],人家源码中的注释已经说明了,我粘过来你看下:

/**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

#5


引用 2 楼 soton_dolphin 的回复:
比如 一个Set  s有 A, B,C
ArrayList a = new ArrayList(s);

如果直接赋值,当s删减或者增加元素的时候,a 也会受影响


引用 4 楼 bigbaldy 的回复:
拷贝的问题楼上已经有人讲了,我就不说了,我说下a.getClass()!=Object[].class,这个是因为toArray()的实现方式不同,ArrayList的toArray返回的是Object[],而其他的就可能不是,例如Arrays.asList("1").toArrary()这个返回的是String[],人家源码中的注释已经说明了,我粘过来你看下:

/**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

我明白了你的意思,但是我还是不懂为什么要判断这个,判断这个有什么意义呢?比如像你说的String[]不满足 ,那么就可以直接把此时的collection转换的集合直接赋值给array?这样直接操作ArrayList肯定会对collection造成影响啊。