天天看點

Java中的Arrays、ArrayList、Vector、Collections差別

一、Arrays

API中的解釋http://docs.oracle.com/javase/1.5.0/docs/api

簡單學 http://hi.baidu.com/chen_767/item/8195fcab4551f2f415329bf4

http://blog.sina.com.cn/s/blog_8c53d73f0100y74d.html

數組是一個動态的,也就是說,它的大小可以根據輸入來測定。例如:

Scanner s=new Scanner(System.in);
int n=s.nextInt();
int[] array=new int[n];
           

輸出數組的方式:

1、循環輸出

2、作為集合輸出:System.out.println(Arrays.asList(數組));

注意:對于int[]數組不能直接這樣做,因為asList()方法的參數必須是對象。應該先把int[]轉化為Integer[]。對于其他primitive類型的數組也是如此,必須先轉換成相應的wrapper類型數組。

int[] a={1,2,3,4};
Integer[] integer=new Integer[a.length];
for(int i=0;i<a.length-1;i++){
	Integer ing=a[i];
	integer[i]=ing;
}
           

3、toString()方法:System.out.println(Arrays.toString(數組));

同樣,這個方法也需要上面2、的轉換,才可以用這個方法正确輸出。

快速複制數組:

1、使用循環結構 這種方法最靈活。唯一不足的地方可能就是代碼較多 

2、 使用Object類的clone() 方法, 這種方法最簡單,得到原數組的一個副本。靈活形也最差。效率最差,尤其是在數組元素很大或者複制對象數組時。

3 、使用Systems的arraycopy 這種方法被告之速度最快,并且靈活性也較好,可以指定原數組名稱、以及元素的開始位置、複制的元素的個數,目标數組名稱、目标數組的位置。

System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

4、Arrarys類的copyOf()方法與copyOfRange()方法可實作對數組的複制。

二、ArrayList

API中的解釋 http://docs.oracle.com/javase/1.5.0/docs/api/

ArrayList詳解 http://blog.csdn.net/tianmo2010/article/details/7046602

與Arrays的比較 http://hi.baidu.com/zhangrg_123/item/17aa446d334bd80ba0cf0f41

http://www.cnblogs.com/ITEagle/archive/2010/02/04/1663719.html

ArrayList是Array的複雜版本,通過add()和get()方法來增加和擷取元素,比Array少了[]而已。

ArrayList實作了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。 size,isEmpty,get,set方法運作時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運作時間為線性。 每個ArrayList執行個體都有一個容量(Capacity),即用于存儲元素的數組的大小。這個容量可随着不斷添加新元素而自動增加,但是增長算法 并沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。 和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。

下面是ensureCapacity()方法的使用效率

import java.util.*;

public class Practice {
	public static void main(String[] args){
		final int N = 1000000;
		Object obj = new Object();
		
		//沒用調用ensureCapacity()方法初始化ArrayList對象
		ArrayList list = new ArrayList();
		long startTime = System.currentTimeMillis();
		for(int i=0;i<=N;i++){
			list.add(obj);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("沒有調用ensureCapacity()方法所用時間:" + (endTime - startTime) + "ms");
		
		//調用ensureCapacity()方法初始化ArrayList對象
		list = new ArrayList();
		startTime = System.currentTimeMillis();
		list.ensureCapacity(N);//預先設定list的大小
		for(int i=0;i<=N;i++){
			list.add(obj);
		}
		endTime = System.currentTimeMillis();
		System.out.println("調用ensureCapacity()方法所用時間:" + (endTime - startTime) + "ms");
		
		//初始化容量
		list = new ArrayList(N);
		startTime = System.currentTimeMillis();
		for(int i=0;i<=N;i++){
			list.add(obj);
		}
		endTime = System.currentTimeMillis();
		System.out.println("調用ensureCapacity()方法所用時間:" + (endTime - startTime) + "ms");
	}
}
           

運作結果:

沒有調用ensureCapacity()方法所用時間:28ms

調用ensureCapacity()方法所用時間:24ms

使用初始化容量的方法所用時間:21ms

【引用】

1.   如果你不能确定ensureCapacity()方法到底是幹嘛用的,最好不要随便用它。 

2.   指定位置來往ArrayList中插入元素有可能引用元素的大量移動,是極其影響效率的,也不要濫用。 

      任何一個ArrayList對象都有一個capacity屬性,用來訓示該ArrayList的最小容量,用“容量”這個詞容易引起像本貼樓主那樣的誤解,我覺得用“容納能力”比較貼切。

      我們知道ArrayList的内部是采用數組來存儲元素的,由于java數組都是定長的,是以這個數組的大小一定是固定的,這個大小就是capacity。我們可以肯定capacity一定是大于或等于ArrayList的size,那麼當size不斷增加到了要超過capacity的時候,ArrayList就不得不重新建立新的capacity來容納更多的元素,這時需要首先建立一個更長的數組,将原來的數組中的元素複制到新數組中,再删除原來的數組。可見當ArrayList越來越大時,這種操作的消耗也是越來越大的。 

      為了減少這種不必要的重建capacity的操作,當我們能肯定ArrayList大緻有多大(或者至少會有多大)時,我們可以先讓ArrayList把capacity設為我們期望的大小,以避免多餘的數組重建。 

      假設ArrayList自動把capacity設為10,每次重建時将長度遞增原來的三分之二,那麼當我們需要大約存儲50個元素到ArrayList中時,就會大約需要重建數組4次,分别是在增加第11、第17、第26、第39個元素的時候進行的。如果我們一開始就讓ArrayList的capacity為50,那麼不需要任何數組重建就能完成所有插入操作了。 

       java允許我們在構造ArrayList的同時指定capacity,如new   ArrayList(50),也允許在以後将它設得更大,而增大capacity就是使用ensureCapacity()方法。注意:capacity隻能比原來的更大,而不能比原來的更小,否則java會忽略該操作。ArrayList的初始預設capacity為10,是以給capacity指定小于10的整數是毫無意義的。 

       最後說說ArrayList的size,前面說過,size一定小于等于capactiy,而且更重要的是,通路超過size的位置将抛出異常,盡管這個位置可能沒有超過capacity。ensureCapacity()隻可能增加capacity,而不會對size有任何影響。要增加size,隻能用add()方法。

二、Vector

API中的解釋 http://www.blogjava.net/Yang/archive/2006/01/05/26662.html

三、Collections

API中的解釋 http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html

基礎學習Collections   http://sunboyyyl.blog.163.com/blog/static/224738120121741039291/

關于Java Collections API不知道的5件事(第一部分)(深入學習) http://www.ibm.com/developerworks/cn/java/j-5things2.html

關于Java Collections API不知道的5件事(第二部分)(深入學習)http://www.ibm.com/developerworks/cn/java/j-5things3.html

 如何周遊Collection中的每一個元素?

   1、不論Collection的實際類型如何,它都支援一個iterator()的方法,該方法傳回一個疊代子,使用該疊代子即可逐一通路Collection中每一個元素。典型的用法如下:  

Iterator it = collection.iterator(); // 獲得一個疊代子 
while(it.hasNext()) {  
Object obj = it.next(); // 得到下一個元素  
}
           

          2、或者直接輸出:

        System.out.println(Collection  collection);

          3、容器類預設沒有考慮線程安全問題,必須自行實作同步,如:

synchronized(arraylist)
{
  arraylist.add(new someclass());
}
           

事實上,可以傳回一個同步化的容器對象,使用java.util.Collections的synchronizedXXX()方法,如:

List list=Collections.synchronizedList(new ArrayList());
           

雖然傳回的對象是同步化的,在存取資料時會進行同步化的工作,但使用Iterator周遊對象時,list使用Iterator()方法傳回的Iterator對象并沒有保證線程的安全,是以周遊時仍必須實作同步化,如:

List list=Collections.synchronizedList(new ArrayList());
synchronized(list)
{ 
Iterator i=list.iterator();
while(i.hasNext())
System.out.println(i.next());
}