Arrays.asList 爲何不能 add 或者 remove 而 ArrayList 能夠

分析以下例子:java

 1 import java.util.Arrays;  2 import java.util.List;  3  4  5 public class Test {  6 public static void main(String[] args) {  7 Integer[] a = {0,1,2,3,4,5,6};  8 List<Integer> c = Arrays.asList(a);  9 for (Integer integer : c) { 10  System.out.println(integer); 11  } 12 c.add(7); 13 c.remove(0); 14 15  } 16 }

打印結果爲:數組

0
1
2
3
4
5
6
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:151)
	at java.util.AbstractList.add(AbstractList.java:89)
	at com.cys.collections.MapTest.main(MapTest.java:14)

查看Arrays.asList() 底層實現:spa

   public static <T> List<T> asList(T... a) {
	return new ArrayList<T>(a);
    }

實現一樣是ArrayList ! But,再向下看:code

文件名: Arrays$ArrayList.class 代表ArrayList是一個Arrays 類的內部類,與咱們平時使用的ArrayList 並不一樣;對象

它繼承了一個抽象類AbstractList並使用該抽象類的add 和 remove方法:blog

 public boolean add(E o) {
	add(size(), o);
	return true;
    }

public void add(int index, E element) {
	throw new UnsupportedOperationException();
    }
 public E remove(int index) {
	throw new UnsupportedOperationException();
    }

  所有拋出了一個UnsupportedOperationException 異常,說明該list不支持改變它長度的狀況。繼承

     可是一樣是數組實現的直接  new 的 ArrayList爲何就能夠呢?內存

  讓咱們看一看它的add 代碼:ci

    

 1  public boolean add(E o) {  2 ensureCapacity(size + 1); // Increments modCount!!  3 elementData[size++] = o;  4 return true;  5  } 
  public boolean addAll(Collection<? extends E> c) {
	Object[] a = c.toArray();
        int numNew = a.length;
	ensureCapacity(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
	return numNew != 0;
    }

  

這兩個方法裏面的第一行,均是確信當前容量是否能容下新增長的對象。element

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;
	    elementData = (E[])new Object[newCapacity];
	    System.arraycopy(oldData, 0, elementData, 0, size);
	}
    }

  此方法裏,一旦發現容量不足,會自動擴充容量,新的大小是

     int newCapacity = (oldCapacity * 3)/2 + 1

     再經過拷貝方法,新new一個數組。

  remove 就很簡單了,就是單純的刪去一個位置上的數據,而後把後面的數據依次向前挪。

     因此 new ArrayList 能夠 remove 和add 。

    題外話:

    咱們看到ArrayList 的擴充是原來的1.5倍+1,因此爲了不頻繁擴充帶來的擴充損耗,應當儘量大的new ArrayList的初始長度,

可是太大的話,若是數據增加很慢,就會佔用不少沒用的內存,因此這個長度仍是須要根據業務的實際狀況,合理申請。

      http://www.cnblogs.com/caoyusongnet/

相關文章
相關標籤/搜索