對比Java的ArrayList與.net的List


今天看見一位園友寫了一篇非常詳細的文章《ArrayList源碼分析》,很佩服寫的如此仔細和詳細。

在看這篇文章時,我也和.net的List<T>做了對比,因為我非常熟悉List<T>的實現,就寫了此篇文章說明各自實現的差異。

  • 存儲
//Java
private transient Object[] elementData;

Java的此類雖然對外是泛型的,但內部卻不是使用泛型的數組存儲,沒有.net好;

//.net
private T[] _items;
  • 默認構造
//Java
public ArrayList() {
this(10);

Java默認構建了大小為10的數組,事實上,很多的時候我們開始根本不存儲數據,而.net默認是0,而且使用一個靜態的0數組實例,.net要聰明的多。

//.net
public List()
{
    this._items = List<T>._emptyArray;
}
  • 添加數據
//java
public boolean add(E e) {
    ensureCapacity(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
    }

顯然,無論數組是否大小夠用,java都會嘗試調用ensureCapacity方法,雖然此方法大多數並不會擴大數組(足夠空間),但這造成了多調用一次方法。.net在這一塊非常的小心。

//.net
public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}

在擴充多大的問題上,大家的意見似乎不一致,

//Java
     public void ensureCapacity(int minCapacity) {
     modCount++;
     int oldCapacity = elementData.length;
     if (minCapacity > oldCapacity) {
         Object oldData[] = elementData;
         int newCapacity = (oldCapacity * 3)/2 + 1;
             if (newCapacity < minCapacity)
         newCapacity = minCapacity;
             // minCapacity is usually close to size, so this is a win:
             elementData = Arrays.copyOf(elementData, newCapacity);
     }
     }

Java使用奇怪的比例,增加2/3大小,而.net似乎很簡單,增加2倍,具體誰更科學,我還做不出判斷。

//.net
private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num > 2146435071)
        {
            num = 2146435071;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}
  • 添加一批數據
//java
public boolean addAll(int index, Collection<? extends E> c) {
     if (index > size || index < 0)
         throw new IndexOutOfBoundsException(
         "Index: " + index + ", Size: " + size);
 
     Object[] a = c.toArray();
     int numNew = a.length;
     ensureCapacity(size + numNew);  // Increments modCount
 
     int numMoved = size - index;
     if (numMoved > 0)
         System.arraycopy(elementData, index, elementData, index + numNew,
                  numMoved);
 
         System.arraycopy(a, 0, elementData, index, numNew);
     size += numNew;
     return numNew != 0;
     }

 

添加一批數據時,在擴充大小時,java首先做一次復制(toArray)到臨時數組,然后再復制到實際數組elementData。

//.net
ICollection<T> collection2 = collection as ICollection<T>;
    if (collection2 != null)
    {
        int count = collection2.Count;
        if (count > 0)
        {
            this.EnsureCapacity(this._size + count);
            if (index < this._size)
            {
                Array.Copy(this._items, index, this._items, index + count, this._size - index);
            }
            if (this == collection2)
            {
                Array.Copy(this._items, 0, this._items, index, index);
                Array.Copy(this._items, index + count, this._items, index * 2, this._size - index);
            }
            else
            {
                T[] array = new T[count];
                collection2.CopyTo(array, 0);
                array.CopyTo(this._items, index);
            }
            this._size += count;
        }
    }

.net 的代碼我看起來非常的奇怪,理論上,他可以調用collection2的copyto直接存入this._items的指定位置,這樣就減少了一次復制,但不知道為什么他沒有這樣做。

  • 其他的不同

判斷項目相等,java用的是對象的相等方法,而.net用的是泛型版本的相等運算,效率更高。Clear時清除數據內容時使用for循環,而.net調用了Array的快速方法。

還有其他的不同嘛?我目前沒有找到,感覺大部分的時候差別不大,可能.net稍微細致一些,你覺得呢?

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM