java中的ArrayList 、List、LinkedList、Collection關系詳解
一、基礎介紹(Set、List、Map)
- Set(集):集合中的元素不按特定方式排序,並且沒有重復對象。他的有些實現類能對集合中的對象按特定方式排序。
- List(列表):集合中的元素按索引位置排序,可以有重復對象,允許按照對象在集合中的索引位置檢索對象。
- Map(映射):集合中的每一個元素包含一對鍵對象和值對象,集合中沒有重復的鍵對象,值對象可以重復。他的有些實現類能對集合中的鍵對象進行排序。
二、基本接口和類型
1、Iterator接口
該接口允許遍歷集合中的所有元素,一共有三個方法:
- public boolean hasNext():判斷是否還有下一個元素。
- public Object next():取得下一個元素,注意返回值為 Object,可能需要類型轉換。如果不再有可取元素,則拋出NoSuchElementException異常。在使用該方法之前,必須先使用hasNext()方法判斷。
- public void remove():刪除當前元素,很少用。
2、Collection接口
該接口是Set和List的父接口,主要提供了下面的方法:
- public boolean add(Object?o):往集合中添加新元素。添加成功,返回true,否則返回false。
- public Iterator iterator():返回Iterator對象,這樣就可以遍歷集合中的所有元素了。
- public boolean contains(Object?o):判斷集合中是否包含指定的元素。
- public int size():取得集合中元素的個數。
- public void clear():刪除集合中的所有元素。
Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,JavaSDK提供的類都是繼承自Collection的“子接口”如List和Set。
所有實現Collection接口的類都必須提供兩個標准的構造函數:無參數的構造函數用於創建一個空的Collection,有一個Collection參數的構造函數用於創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。后一個構造函數允許用戶復制一個Collection。
如何遍歷Collection中的每一個元素?不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個元素。典型的用法如下:
Iterator it = collection.iterator(); // 獲得一個迭代子 while(it.hasNext()) { Object obj = it.next(); // 得到下一個元素 }
3、Set集合
Set是最簡單的集合,集合中的對象不按照特定的方式排序。主要有如下兩個實現:HashSet和TreeSet
3.1 HashSet
HashSet類按照哈希算法來存取集合中的對象,具有很好的存取性能。當HashSet向集合中加入一個對象時,會調用對象的hashCode()方法獲取哈希碼,然后根據這個哈希碼進一步計算出對象在集合中的存放位置。
3.2 TreeSet
TreeSet實現了SortedSet接口,可以對集合中的元素排序。如何排序的內容請參考其他文檔,這里不做詳述。
4、List集合
List繼承自Collection接口。List是一種有序集合,List中的元素可以根據索引(順序號:元素在集合中處於的位置信息)進行取得/刪除/插入操作。
跟Set集合不同的是,List允許有重復元素。對於滿足e1.equals(e2)條件的e1與e2對象元素,可以同時存在於List集合中。當然,也有List的實現類不允許重復元素的存在。同時,List還提供一個listIterator()方法,返回一個ListIterator接口對象,和Iterator接口相比,ListIterator添加元素的添加,刪除,和設定等方法,還能向前或向后遍歷,具體的方法往下看。List接口的實現類主要有ArrayList,LinkedList,Vector,Stack等。
4.1 ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨着不斷添加新元素而自動增加,但是增長算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
4.1.1 主要方法:
- public boolean add(Object?o):添加元素
- public void add(int index, Object element):在指定位置添加元素
- public Iterator iterator():取得Iterator對象便於遍歷所有元素
- public Object get(int?index):根據索引獲取指定位置的元素
- public Object set(int index,Object element):替換掉指定位置的元素
4.1.2 排序方法:
- Collections.sort(List list):對List的元素進行自然排序
- Collections.sort(List list, Comparator comparator):對List中的元素進行客戶化排序
4.2 LinkedList類
LinkedList實現了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
5、Map
- Map是一種把鍵對象和值對象進行映射的集合,它的每一個元素都包含一對鍵對象和值對象。
- 向Map添加元素時,必須提供鍵對象和值對象。
- 從Map中檢索元素時,只要給出鍵對象,就可以返回對應的值對象。
- 鍵對象不能重復,但值對象可以重復。
- Map有兩種常見的實現類:HashMap和TreeMap。
5.1 HashMap
HashMap按照哈希算法來存取鍵對象,有很好的存取性能。和HashSet一樣,要求當兩個鍵對象通過equals()方法比較為true時,這兩個鍵對象的hashCode()方法返回的哈希碼也一樣。
5.2 TreeMap
TreeMap實現了SortedMap接口,能對鍵對象進行排序。同TreeSet一樣,TreeMap也支持自然排序和客戶化排序兩種方式。
5.3 方法列表
- public Object put(Object key, Object value):插入元素
- public Object get(Object?key):根據鍵對象獲取值對象
- public Set keySet():取得所有鍵對象集合
- public Collection values():取得所有值對象集合
- public Set entrySet():取得Map.Entry對象集合,一個Map.Entry代表一個Map中的元素
6、總結
如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。 盡量返回接口而非實際的類型,如返回List而非ArrayList,這樣如果以后需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。