ArrayList的addAll 与 for循环比较

来源:互联网 发布:赛尔号刷米币软件 编辑:程序博客网 时间:2024/05/16 01:55


采摘处:http://blog.csdn.net/sutaizi/article/details/6607123


问题是这样产生的,网上一哥们发了一个面试题:

ListA 里面有  1   2    3 


ListB里面有  4    5   6 


让ListA变成  1  2  3  4  5  6 

我觉得很简单 ,就说用for循环遍历 添加就好了。结果面试官说

答案是使用addAll方法,因为这样效率高:

我表示很费解,于是查阅了资料。

得出以下结论:

在小数据量时,for循环效率高,大数据量时addAll方法效率高:

原因如下:

ArrayList的addAll的实现为:

[java] view plaincopy
  1. public   boolean   addAll(Collection   c)   {   
  2.                          Object[]   a   =   c.toArray();   
  3.                          int   numNew   =   a.length;   
  4. ensureCapacity(size   +   numNew);      //   Increments   modCount   
  5.                          System.arraycopy(a,   0,   elementData,   size,   numNew);   
  6.                          size   +=   numNew;   
  7. return   numNew   !=   0;   
  8.              }   

 

很显然。。在拷贝数组时使用了


arraycopy 这个方法。这个方法是使用拷贝内存的做法 ,效率比遍历数组块很多。

首先找到数据源 然后将该段内存拷贝。

 

当然值得注意的是,这个函数中还使用了toArray方法,这个方法是 要遍历操作的

 

但是如果需要多次遍历,那么addAll还是在性能上会获取优势的. .

下面是网上的一个测试 在20组数据时 还是 for效率高,但是在大数据量的时候 arraycopy 方法就明显占优势了。
http://www.exam8.com/computer/djks/dj2/Java/ziliao/200810/1314435.htmlhttp://www.exam8.com/computer/djks/dj2/Java/ziliao/200810/1314435.html

另外:

arraycopy的定义是这样的

public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos,int length);

 

native关键字的意思是 这个函数的源码在JDK中没有的。但是他调用的是本地计算机中的函数

这个函数是C,或者C++写完的,编译成DLL。 java调用。所以效率比for循环要块。

 

综上所述 :为什么在大数据量时使用addall方法效率快?

1.使用内存拷贝,移动数据。

2.本地函数,执行效率高。

那小数据量时呢?

以上2点都不明显,并且首先要调用toArray方法,在小数据量时,效果没有for来的好。




采摘者:


   /**     * Adds the objects in the specified collection to this {@code ArrayList}.     *     * @param collection     *            the collection of objects.     * @return {@code true} if this {@code ArrayList} is modified, {@code false}     *         otherwise.     */    @Override public boolean addAll(Collection<? extends E> collection) {        Object[] newPart = collection.toArray();        int newPartSize = newPart.length;        if (newPartSize == 0) {            return false;        }        Object[] a = array;        int s = size;        int newSize = s + newPartSize; // If add overflows, arraycopy will fail        if (newSize > a.length) {            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room            Object[] newArray = new Object[newCapacity];            System.arraycopy(a, 0, newArray, 0, s);            array = a = newArray;        }        System.arraycopy(newPart, 0, a, s, newPartSize);        size = newSize;        modCount++;        return true;    }    /**     * Inserts the objects in the specified collection at the specified location     * in this List. The objects are added in the order they are returned from     * the collection's iterator.     *     * @param index     *            the index at which to insert.     * @param collection     *            the collection of objects.     * @return {@code true} if this {@code ArrayList} is modified, {@code false}     *         otherwise.     * @throws IndexOutOfBoundsException     *             when {@code location < 0 || > size()}     */    @Override    public boolean addAll(int index, Collection<? extends E> collection) {        int s = size;        if (index > s || index < 0) {            throwIndexOutOfBoundsException(index, s);        }        Object[] newPart = collection.toArray();        int newPartSize = newPart.length;        if (newPartSize == 0) {            return false;        }        Object[] a = array;        int newSize = s + newPartSize; // If add overflows, arraycopy will fail        if (newSize <= a.length) {             System.arraycopy(a, index, a, index + newPartSize, s - index);        } else {            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room            Object[] newArray = new Object[newCapacity];            System.arraycopy(a, 0, newArray, 0, index);            System.arraycopy(a, index, newArray, index + newPartSize, s-index);            array = a = newArray;        }        System.arraycopy(newPart, 0, a, index, newPartSize);        size = newSize;        modCount++;        return true;    }