弱引用集合
『壹』 不是List介面下的集合類
3、Set介面
Set不保存重復的元素。Set中最常被使用的是測試歸屬性,你可以很容易的詢問某個對象是否在某個Set中。
Set具有與Collection完全一樣的介面,因此沒有任何額外的功能。實際上Set就是Collection,只是行為不同。
(1)HashSet類(散列存放元素的類,不允許有重復的元素,是一種很復雜的數據介面)
HashSet使用的是相當復雜的方式來存儲元素的,使用HashSet能夠最快的獲取集合中的元素,效率非常高(以空間換時間)。
會根據hashcode和equals來龐端是否是同一個對象,如果hashcode一樣,並且equals返回true,則是同一個對象,不能重復存放。
HashSet存儲之所以沒有順序是因為在存儲的時候會將元素進行compare之後存放到一個二叉樹裡面,這樣在拿數據的時候
就能夠根據二叉樹的數據結構快速的獲取到指定的元素。
(2)SortedSet類
對插入的元素進行排序的Set集合。
(3)LinkedHashSet類(這是一個更復雜的數據結構的存儲,不過用的比較少)
LinkedHashSet按照插入順序保存對象,同時還保存了HashSet的查詢速度。
(4)TreeSet類
TreeSet也不能存放重復對象,但是TreeSet會自動排序,如果存放的對象不能排序則會報錯,所以存放的對象必須指定排序規則。
排序規則包括自然排序和自定義排序。
①自然排序:TreeSet要添加哪個對象就在哪個對象類上面實現java.lang.Comparable介面,並且重寫comparaTo()方法,
返回0則表示是同一個對象,否則為不同對象。
②客戶排序:建立一個第三方類並實現java.util.Comparator介面。並重寫方法。
定義集合形式為TreeSet ts = new TreeSet(new 第三方類());
4、Map介面(是採用鍵值對的形式存儲數據,這樣就能夠通過鍵獲取到對應的值的方式,Map<K,V>必須要有泛型 )
請注意,Map沒有繼承Collection介面,Map提供key到value的映射。一個Map中不能包含相同的key,
每個key只能映射一個 value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
Map介面提供兩個基本的方法:push(key,value);向集合中放置元素get(key);按照鍵獲取值元素。
提供兩個轉換的方法:
Set<String> set=map.keySet(); 獲取所有的key的Set視圖
Collection<Double> col=map.values();獲取所有的vlue視圖。
「集合框架」提供兩種常規的Map實現:HashMap和TreeMap (TreeMap實現SortedMap介面)。在Map 中插入、刪除和定位元素,
HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。使用HashMap要求添加的鍵類明確定
義了hashCode()和equals()的實現。
(1)HashMap類
Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。
增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現
hashCode和equals方 法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,
如果兩個對象相 同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,
如 果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的
hashCode()方法,能加快哈希 表的操作。如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果
(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
(2)Hashtable類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap 的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
(3)weekHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收
5、Iterator類,作為集合中比較重要的迭代類,主要作用就是集合數據的遍歷顯示。
集合類中都能夠獲取到一個迭代的類,用來執行迭代的操作。
Iterator it = collection.iterator()
主要包括以下幾個方法:
hasNext();判斷是否有下一個元素
next();獲取下一個元素
『貳』 大公司Java集合類面試問題你知道多少
介面:Collection
Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的「子介面」如List和Set。
所有實現Collection介面的類都必須提供兩個標準的構造函數:無參數的構造函數用於創建一個空的Collection,有一個Collection參數的構造函數用於創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。後一個構造函數允許用戶復制一個Collection。
主要的一個介面方法:boolean add(Ojbect c)
雖然返回的是boolean,但不是表示添加成功與否,這個返回值表示的意義是add()執行後,集合的內容是否改變了(就是元素的數量、位置等有無變化)。類似的addAll,remove,removeAll,remainAll也是一樣的。
用Iterator模式實現遍歷集合
Collection有一個重要的方法:iterator(),返回一個Iterator(迭代器),用於遍歷集合的所有元素。Iterator模式可以把訪問邏輯從不同的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。典型的用法如下:
Iterator it = collection.iterator(); //獲得一個迭代器
while(it.hasNext()) {
Object obj = it.next(); //得到下一個元素
}
不需要維護遍歷集合的「指針」,所有的內部狀態都由Iterator來維護,而這個Iterator由集合類通過工廠方法生成。
每一種集合類返回的Iterator具體類型可能不同,但它們都實現了Iterator介面,因此,我們不需要關心到底是哪種Iterator,它只需要獲得這個Iterator介面即可,這就是介面的好處,面向對象的威力。
要確保遍歷過程順利完成,必須保證遍歷過程中不更改集合的內容(Iterator的remove()方法除外),所以,確保遍歷可靠的原則是:只在一個線程中使用這個集合,或者在多線程中對遍歷代碼進行同步。
由Collection介面派生的兩個介面是List和Set。
List介面
List是有序的Collection,使用此介面能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。和下面要提到的Set不同,List允許有相同的元素。
除了具有Collection介面必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator介面,和標準的Iterator介面相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向後遍歷。
實現List介面的常用類有LinkedList,ArrayList,Vector和Stack。
LinkedList類
LinkedList實現了List介面,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(…));
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。
Vector類
Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一介面,但是,因為Vector是同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出,因此必須捕獲該異常。
Stack類
Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建後是空棧。
Set介面
Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重復的元素。
請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
Map介面
請注意,Map沒有繼承Collection介面,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
Hashtable類
Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」:
Hashtable numbers = new Hashtable();
numbers.put(「one」, new Integer(1));
numbers.put(「two」, new Integer(2));
numbers.put(「three」, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(「two」);
System.out.println(「two = 」 + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代器操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收。
總結
·如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
·如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。
·要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。
·盡量返回介面而非實際的類型,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。
『叄』 如何索引LinkedList, Iterator是臨時的:
ArrayList Vector LinkedList 區別與用法最近用到了,所以依然是轉載 ArrayList 和Vector是採用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,都允許直接序號索引元素,但是插入數據要設計到數組元素移動等內存操作,所以索引數據快插入數據慢,Vector由於使用了synchronized方法(線程安全)所以性能上比ArrayList要差,LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行向前或向後遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快!線性表,鏈表,哈希表是常用的數據結構,在進行Java開發時,JDK已經為我們提供了一系列相應的類來實現基本的數據結構。這些類均在java.util包中。本文試圖通過簡單的描述,向讀者闡述各個類的作用以及如何正確使用這些類。 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection介面 Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的「子介面」如List和Set。 所有實現Collection介面的類都必須提供兩個標準的構造函數:無參數的構造函數用於創建一個空的Collection,有一個Collection參數的構造函數用於創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。後一個構造函數允許用戶復制一個Collection。 如何遍歷Collection中的每一個元素?不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個元素。典型的用法如下: Iterator it = collection.iterator(); // 獲得一個迭代子 while(it.hasNext()) 由Collection介面派生的兩個介面是List和Set。 List介面 List是有序的Collection,使用此介面能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。和下面要提到的Set不同,List允許有相同的元素。 除了具有Collection介面必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator介面,和標準的Iterator介面相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向後遍歷。 實現List介面的常用類有LinkedList,ArrayList,Vector和Stack。 LinkedList類 LinkedList實現了List介面,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。 注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List: List list = Collections.synchronizedList(new LinkedList(...)); ArrayList類 ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。 size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。 每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。 和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。 Vector類 Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一介面,但是,因為Vector是同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出,因此必須捕獲該異常。 Stack 類 Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建後是空棧。 Set介面 Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。 很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重復的元素。 請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。 Map介面 請注意,Map沒有繼承Collection介面,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。 Hashtable類 Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。 添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。 Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」: Hashtable numbers = new Hashtable(); numbers.put(「one」, new Integer(1)); numbers.put(「two」, new Integer(2)); numbers.put(「three」, new Integer(3)); 要取出一個數,比如2,用相應的key: Integer n = (Integer)numbers.get(「two」); System.out.println(「two = 」 + n); 由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。 如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。 Hashtable是同步的。 HashMap類 HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。 WeakHashMap類 WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收。總結 如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。 如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。 要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。 盡量返回介面而非實際的類型,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。同步性 Vector是同步的。這個類中的一些方法保證了Vector中的對象是線程安全的。而ArrayList則是非同步的,因此ArrayList中的對象並不是線程安全的。因為同步的要求會影響執行的效率,所以如果你不需要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣可以避免由於同步帶來的不必要的性能開銷。數據增長從內部實現機制來講ArrayList和Vector都是使用數組(Array)來控制集合中的對象。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那麼使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。使用模式在ArrayList和Vector中,從一個指定的位置(通過索引)查找數據或是在集合的末尾增加、移除一個元素所花費的時間是一樣的,這個時間我們用O(1)表示。但是,如果在集合的其他位置增加或移除元素那麼花費的時間會呈線形增長:O(n-i),其中n代表集合中元素的個數,i代表元素增加或移除元素的索引位置。為什麼會這樣呢?以為在進行上述操作的時候集合中第i和第i個元素之後的所有元素都要執行位移的操作。這一切意味著什麼呢?這意味著,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那麼使用Vector或ArrayList都可以。如果是其他操作,你最好選擇其他的集合操作類。比如,LinkList集合類在增加或移除集合中任何位置的元素所花費的時間都是一樣的?O(1),但它在索引一個元素的使用缺比較慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因為你可以簡單的使用索引來代替創建iterator對象的操作。LinkList也會為每個插入的元素創建對象,所有你要明白它也會帶來額外的開銷。最後,在《Practical Java》一書中Peter Haggar建議使用一個簡單的數組(Array)來代替Vector或ArrayList。尤其是對於執行效率要求高的程序更應如此。因為使用數組(Array)避免了同步、額外的方法調用和不必要的重新分配空間的操作
『肆』 求大神,java的集合框架是什麼意思
Java平台提供了一個全新的集合框架。「集合框架」主要由一組用來操作對象的介面組成。不同介面描述一組不同數據類型。
Java 2集合框架圖
集合介面:6個介面(短虛線表示),表示不同集合類型,是集合框架的基礎。
抽象類:5個抽象類(長虛線表示),對集合介面的部分實現。可擴展為自定義集合類。
實現類:8個實現類(實線表示),對介面的具體實現。
在很大程度上,一旦您理解了介面,您就理解了框架。雖然您總要創建介面特定的實現,但訪問實際集合的方法應該限制在介面方法的使用上;因此,允許您更改基本的數據結構而不必改變其它代碼。
· Collection 介面是一組允許重復的對象。
· Set 介面繼承 Collection,但不允許重復,使用自己內部的一個排列機制。
· List 介面繼承 Collection,允許重復,以元素安插的次序來放置元素,不會重新排列。
· Map介面是一組成對的鍵-值對象,即所持有的是key-value pairs。Map中不能有重復的key。擁有自己的內部排列機制。
· 容器中的元素類型都為Object。從容器取得元素時,必須把它轉換成原來的類型。
Java 2簡化集合框架圖
集合介面
1.Collection 介面
用於表示任何對象或元素組。想要盡可能以常規方式處理一組元素時,就使用這一介面。
(1) 單元素添加、刪除操作:
boolean add(Object o):將對象添加給集合
boolean remove(Object o): 如果集合中有與o相匹配的對象,則刪除對象o
(2) 查詢操作:
int size() :返回當前集合中元素的數量
boolean isEmpty() :判斷集合中是否有任何元素
boolean contains(Object o) :查找集合中是否含有對象o
Iterator iterator() :返回一個迭代器,用來訪問集合中的各個元素
(3) 組操作 :作用於元素組或整個集合
boolean containsAll(Collection c): 查找集合中是否含有集合c 中所有元素
boolean addAll(Collection c) : 將集合c 中所有元素添加給該集合
void clear(): 刪除集合中所有元素
void removeAll(Collection c) : 從集合中刪除集合c 中的所有元素
void retainAll(Collection c) : 從集合中刪除集合c 中不包含的元素
(4) Collection轉換為Object數組 :
Object[] toArray() :返回一個內含集合所有元素的array
Object[] toArray(Object[] a) :返回一個內含集合所有元素的array。運行期返回的array和參數a的型別相同,需要轉換為正確型別。
『伍』 Collection介面的Map介面
請注意,Map沒有繼承Collection介面,提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
Hashtable類
Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」:
Hashtable numbers = new Hashtable();
numbers.put(「one」, new Integer(1));
numbers.put(「two」, new Integer(2));
numbers.put(「three」, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(「two」);
System.out.println(「two = 」 + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
HashSet類
參見set。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收。
『陸』 對於集合類哪個對排序支持最好
編輯詞條JAVA容器
解釋一:
容器(Container)
Spring 提供容器功能,容器可以管理對象的生命周期、對象與對象之間的依賴關系,您可以使用一個配置文件(通常是XML),在上面定義好對象的名稱、如何產生(Prototype 方式或Singleton 方式)、哪個對象產生之後必須設定成為某個對象的屬性等,在啟動容器之後,所有的對象都可以直接取用,不用編寫任何一行程序代碼來產生對象,或是建立對象與對象之間的依賴關系。
換個更直白點的說明方式:容器是一個Java 所編寫的程序,原先必須自行編寫程序以管理對象關系,現在容器都會自動幫您作好。
常用容器:WebSphere,WebLogic,Resin,Tomcat
----------------------------------
解釋二:
容器類
Java容器類包含List、ArrayList、Vector及map、HashTable、HashMap
ArrayList和HashMap是非同步的,Vector和HashTable是同步的,所以Vector和HashTable是線程安全的,而 ArrayList和HashMap並不是線程安全的。因為同步需要花費機器時間,所以Vector和HashTable的執行效率要低於 ArrayList和HashMap。
Collection
├List 介面
│├LinkedList 鏈表
│├ArrayList 順序結構動態數組類
│└Vector 向量
│ └Stack 棧
└Set
Map
├Hashtable
├HashMap
└WeakHashMap List介面
List是有序的Collection,使用此介面能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。
和下面要提到的Set不同,List允許有相同的元素。
除了具有Collection介面必備的iterator()方法外,List還提供一個listIterator()方法,返回一個 ListIterator介面,和標準的Iterator介面相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素, 還能向前或向後遍歷。
實現List介面的常用類有LinkedList,ArrayList,Vector和Stack。
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長演算法 並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。
Map介面
請注意,Map沒有繼承Collection介面,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個 value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap 的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
Collection介面
Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自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(); // 得到下一個元素
}
由Collection介面派生的兩個介面是List和Set。
Hashtable類
Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」:
Hashtable numbers = new Hashtable();
numbers.put(「one」, new Integer(1));
numbers.put(「two」, new Integer(2));
numbers.put(「three」, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(「two」);
System.out.println(「two = 」 + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收。
總結
如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。
要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。
盡量返回介面而非實際的類型,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。
同步性
Vector是同步的。這個類中的一些方法保證了Vector中的對象是線程安全的。而ArrayList則是非同步的,因此ArrayList中的對象並不是線程安全的。因為同步的要求會影響執行的效率,所以如果你不需要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣可以避免由於同步帶來的不必要的性能開銷。
數據增長
從內部實現機制來講ArrayList和Vector都是使用數組(Array)來控制集合中的對象。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那麼使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。
使用模式
在ArrayList和Vector中,從一個指定的位置(通過索引)查找數據或是在集合的末尾增加、移除一個元素所花費的時間是一樣的,這個時間我們用O(1)表示。但是,如果在集合的其他位置增加或移除元素那麼花費的時間會呈線形增長:O(n-i),其中n代表集合中元素的個數,i代表元素增加或移除元素的索引位置。為什麼會這樣呢?以為在進行上述操作的時候集合中第i和第i個元素之後的所有元素都要執行位移的操作。這一切意味著什麼呢?
這意味著,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那麼使用Vector或ArrayList都可以。如果是其他操作,你最好選擇其他的集合操作類。比如,LinkList集合類在增加或移除集合中任何位置的元素所花費的時間都是一樣的?O(1),但它在索引一個元素的使用缺比較慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因為你可以簡單的使用索引來代替創建iterator對象的操作。LinkList也會為每個插入的元素創建對象,所有你要明白它也會帶來額外的開銷。
最後,在《Practical Java》一書中Peter Haggar建議使用一個簡單的數組(Array)來代替Vector或ArrayList。尤其是對於執行效率要求高的程序更應如此。因為使用數組(Array)避免了同步、額外的方法調用和不必要的重新分配空間的操作。
理解集合類
集合類存放於java.util包中。
集合類存放的都是對象的引用,而非對象本身,出於表達上的便利,我們稱集合中的對象就是指集合中對象的引用(reference)。
集合類型主要有3種:set(集)、list(列表)和map(映射)。
(1)集
集(set)是最簡單的一種集合,它的對象不按特定方式排序,只是簡單的把對象加入集合中,就像往口袋裡放東西。
對集中成員的訪問和操作是通過集中對象的引用進行的,所以集中不能有重復對象。
集也有多種變體,可以實現排序等功能,如TreeSet,它把對象添加到集中的操作將變為按照某種比較規則將其插入到有序的對象序列中。它實現的是SortedSet介面,也就是加入了對象比較的方法。通過對集中的對象迭代,我們可以得到一個升序的對象集合。
(2)列表
列表的主要特徵是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,當然,它與根本沒有順序的集是不同的。
列表在數據結構中分別表現為:數組和向量、鏈表、堆棧、隊列。
關於實現列表的集合類,是我們日常工作中經常用到的,將在後邊的筆記詳細介紹。
(3)映射
映射與集或列表有明顯區別,映射中每個項都是成對的。映射中存儲的每個對象都有一個相關的關鍵字(Key)對象,關鍵字決定了對象在映射中的存儲位置,檢索對象時必須提供相應的關鍵字,就像在字典中查單詞一樣。關鍵字應該是唯一的。
關鍵字本身並不能決定對象的存儲位置,它需要對過一種散列(hashing)技術來處理,產生一個被稱作散列碼(hash code)的整數值,散列碼通常用作一個偏置量,該偏置量是相對於分配給映射的內存區域起始位置的,由此確定關鍵字/對象對的存儲位置。理想情況下,散列處理應該產生給定范圍內均勻分布的值,而且每個關鍵字應得到不同的散列碼。
集合類簡介
java.util中共有13個類可用於管理集合對象,它們支持集、列表或映射等集合,以下是這些類的簡單介紹
集:
HashSet: 使用HashMap的一個集的實現。雖然集定義成無序,但必須存在某種方法能相當高效地找到一個對象。使用一個HashMap對象實現集的存儲和檢索操作是在固定時間內實現的.
TreeSet: 在集中以升序對對象排序的集的實現。這意味著從一個TreeSet對象獲得第一個迭代器將按升序提供對象。TreeSet類使用了一個TreeMap.
列表:
Vector: 實現一個類似數組一樣的表,自動增加容量來容納你所需的元素。使用下標存儲和檢索對象就象在一個標準的數組中一樣。你也可以用一個迭代器從一個Vector中檢索對象。Vector是唯一的同步容器類??當兩個或多個線程同時訪問時也是性能良好的。
Stack: 這個類從Vector派生而來,並且增加了方法實現棧??一種後進先出的存儲結構。
LinkedList: 實現一個鏈表。由這個類定義的鏈表也可以像棧或隊列一樣被使用。
ArrayList: 實現一個數組,它的規模可變並且能像鏈表一樣被訪問。它提供的功能類似Vector類但不同步。
映射:
HashTable: 實現一個映象,所有的鍵必須非空。為了能高效的工作,定義鍵的類必須實現hashcode()方法和equal()方法。這個類是前面java實現的一個繼承,並且通常能在實現映象的其他類中更好的使用。
HashMap: 實現一個映象,允許存儲空對象,而且允許鍵是空(由於鍵必須是唯一的,當然只能有一個)。
WeakHashMap: 實現這樣一個映象:通常如果一個鍵對一個對象而言不再被引用,鍵/對象對將被舍棄。這與HashMap形成對照,映象中的鍵維持鍵/對象對的生命周期,盡管使用映象的程序不再有對鍵的引用,並且因此不能檢索對象。
TreeMap: 實現這樣一個映象,對象是按鍵升序排列的。
Set和List都是由公共介面Collection擴展而來,所以它們都可以使用一個類型為Collection的變數來引用。這就意味著任何列表或集構成的集合都可以用這種方式引用,只有映射類除外(但也不是完全排除在外,因為可以從映射獲得一個列表。)所以說,把一個列表或集傳遞給方法的標准途徑是使用Collection類型的參數。
『柒』 Java集合框架的操作的方法有哪些怎麼用
淺談JAVA集合框架
Java提供了數種持有對象的方式,包括語言內置的Array,還有就是utilities中提供的容器類(container classes),又稱群集類(collection classes)。集合在java中非常重要,在討論之前,先來看幾個面試中的經典問題。
1 Collection 和 Collections的區別。
2 List, Set, Map是否繼承自Collection介面。
3 ArrayList和Vector的區別。
4 HashMap和Hashtable的區別。
篇尾有答案,我們開始正題。
集合Collection介面
--Collection 是任何對象組,元素各自獨立,通常擁有相同的套用規則。Set List由它派生。
基本操作 增加元素add(Object obj); addAll(Collection c);
刪除元素 remove(Object obj); removeAll(Collection c);
求交集 retainAll(Collection c);
刪除元素 remove(Object obj); removeAll(Collection c);
求交集 retainAll(Collection c);
訪問/遍歷集合元素的好辦法是使用Iterator介面(迭代器用於取代Enumeration)
Public interface Iterator{
Public Boolean hasNext(};
Public Object next(};
Public void remove(};
}
集set
--沒有重復項目的集合
有三種特定類型的集可用
HashSet-基於散列表的集,加進散列表的元素要實現hashCode()方法
LinkedHashSet-對集迭代時,按增加順序返回元素
TreeSet-基於(平衡)樹的數據結構
清單List
--位置性集合。加進清單的元素可以加在清單中特定位置或加到末尾
有兩個特定版本
ArrayList(數組表)-類似於Vector,都用於縮放數組維護集合。區別:
一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的
二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半
LinkedList(鏈表)-是雙向鏈表,每個節點都有兩個指針指向上一節點和下一節點。
用在FIFO,用addList()加入元素 removeFirst()刪除元素
用在FILO,用addFirst()/removeLast()
ListIterator提供雙向遍歷next() previous(),可刪除、替換、增加元素
映射表Map
--用於關鍵字/數值對,像個Dictionary
處理Map的三種集合
關鍵字集KeySet()
數值集value()
項目集enrySet()
四個具體版本
HashMap-散列表的通用映射表
LinkedHashMap-擴展HashMap,對返回集合迭代時,維護插入順序
WeakHashMap-基於弱引用散列表的映射表,如果不保持映射表外的關鍵字的引用,則內存回收程序會回收它
TreeMap-基於平衡樹的映射表
HashMap-散列表的通用映射表
LinkedHashMap-擴展HashMap,對返回集合迭代時,維護插入順序
WeakHashMap-基於弱引用散列表的映射表,如果不保持映射表外的關鍵字的引用,則內存回收程序會回收它
TreeMap-基於平衡樹的映射表
Collections類,用於同步集合,還能改變集合只讀方式的類
e.g.:
Map mp=new HashMap();
mp=Collections.synchronizedMap(mp); //生成線程安全的映射表
mp=Collections.unmodifiableMap(mp); //生成只讀映射表
Comparable 自然順序的排序類 Comparator 面向樹的集合排序類
容器分類學(Container taxonomy)
集合介面: Collection List Set;Map Iterator ListIterator。
抽象類: AbstractCollection AbstractList AbstractSet AbstractMap AbstractSequentiaList。
老版本中的集合類型
Vector類
Vector,就是向量。一種異構的混合體,可以動態增加容量。對它的操作簡要如下
比如我們有一個Vector: Vector myVec=new Vector(a_Array.length)
取得vector的長度:myVec.size();
賦值:set(int position,Object obj) / setElementAt(Object obj, int position) –不支持動態增長
add(Object obj )/ addElement(Object obj) 在Vector末尾加入對象
e.g.:myVec.add(new a_Array[0]);
取出元素:get(int position) / getElement(int position)
Stack類
是Vector的子類。就是數據結構里講濫了的堆棧(這個詞可簡稱棧,不要混淆於heap-堆)。後進先出的存取方式。
Stack()構造空棧
Empty()叛空
Search()檢查堆棧是否有元素
Peek()取得棧頂元素
Pop()彈棧
Push()入棧
Enumeration介面
Dictionary類
字典。關鍵字/數值方式存取數據,如果映射沒有此關鍵字,取回null。
Hashtable類
是Dictionary結構的具體實現。
面試題答案
Collection 和 Collections的區別。
Collections是個java.util下的類,它包含有各種有關集合操作的靜態方法。
Collection是個java.util下的介面,它是各種集合結構的父介面
List, Set, Map是否繼承自Collection介面? List,Set是 Map不是
ArrayList和Vector的區別。
一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的
二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半
HashMap和Hashtable的區別
一.歷史原因:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map介面的一個實現
二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的
三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value
『捌』 如何存儲在數組中的弱引用的對象,字典objc
.NSValue+ (NSValue *)valueWithNonretainedObject:(id)anObject
如果你想將一個對象添加到一個集合,但don,Äôt希望集合,形成強大的參考吧。 2.有一個棘手的塊這樣做:typedef id (^WeakReference)(void);
WeakReference MakeWeakReference (id object) {
__weak id weakref = object;
return ^{ return weakref; };
}
id (WeakReference ref) {
if (ref == nil)
return nil;
else
return ref ();
}
[arr addObject:MakeWeakReference(obj)];
id newobj = ([arr objectAtIndex:0]);
3,採用一個弱指針的值保存自定義的WeakReference類。 其實,設計思路都只是
2. 您NSValue valueWithNonretainedObject:強烈存儲的值弱引用您的目標對象。
『玖』 java 有類似於動態數組的嗎
當然有
從內部實現機制來講ArrayList和Vector都是使用Objec的數組形式來存儲的。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那麼使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。
下面希望對你有幫助
ArrayList Vector LinkedList 區別與用法
ArrayList,LinkedList,Vestor這三個類都實現了java.util.List介面,但它們有各自不同的特性,主要如下:
一、同步性
ArrayList,LinkedList是不同步的,而Vestor是的。所以如果要求線程安全的話,可以使用ArrayList或LinkedList,可以節省為同步而耗費開銷。但在多線程的情況下,有時候就不得不使用Vector了。當然,也可以通過一些辦法包裝ArrayList,LinkedList,使他們也達到同步,但效率可能會有所降低。
二、數據增長
從內部實現機制來講ArrayList和Vector都是使用Objec的數組形式來存儲的。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那麼使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。
三、檢索、插入、刪除對象的效率
ArrayList和Vector中,從指定的位置(用index)檢索一個對象,或在集合的末尾插入、刪除一個對象的時間是一樣的,可表示為O(1)。但是,如果在集合的其他位置增加或移除元素那麼花費的時間會呈線形增長:O(n-i),其中n代表集合中元素的個數,i代表元素增加或移除元素的索引位置。為什麼會這樣呢?以為在進行上述操作的時候集合中第i和第i個元素之後的所有元素都要執行(n-i)個對象的位移操作。
LinkedList中,在插入、刪除集合中任何位置的元素所花費的時間都是一樣的—O(1),但它在索引一個元素的時候比較慢,為O(i),其中i是索引的位置。
所以,如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那麼使用Vector或ArrayList都可以。如果是對其它指定位置的插入、刪除操作,最好選擇LinkedList
ArrayList 和Vector是採用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,都允許直接序號索引元素,但是插入數據要設計到數組元素移動等內存操作,所以索引數據快插入數據慢,Vector由於使用了synchronized方法(線程安全)所以性能上比ArrayList要差,LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行向前或向後遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快!
線性表,鏈表,哈希表是常用的數據結構,在進行Java開發時,JDK已經為我們提供了一系列相應的類來實現基本的數據結構。這些類均在java.util包中。本文試圖通過簡單的描述,向讀者闡述各個類的作用以及如何正確使用這些類。
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection介面
Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自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(); // 得到下一個元素
}
由Collection介面派生的兩個介面是List和Set。
List介面
List是有序的Collection,使用此介面能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組。
和下面要提到的Set不同,List允許有相同的元素。
除了具有Collection介面必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator介面,和標準的Iterator介面相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向後遍歷。
實現List介面的常用類有LinkedList,ArrayList,Vector和Stack。
LinkedList類
LinkedList實現了List介面,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
ArrayList類
ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
每個ArrayList實例都有一個容量(Capacity),即用於存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。
Vector類
Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一介面,但是,因為Vector是同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出,因此必須捕獲該異常。
Stack 類
Stack繼承自Vector,實現一個後進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建後是空棧。
Set介面
Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重復的元素。
請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。
Map介面
請注意,Map沒有繼承Collection介面,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map介面提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。
Hashtable類
Hashtable繼承Map介面,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
Hashtable通過initial capacity和load factor兩個參數調整性能。通常預設的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是」one」,」two」,」three」:
Hashtable numbers = new Hashtable();
numbers.put(「one」, new Integer(1));
numbers.put(「two」, new Integer(2));
numbers.put(「three」, new Integer(3));
要取出一個數,比如2,用相應的key:
Integer n = (Integer)numbers.get(「two」);
System.out.println(「two = 」 + n);
由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
HashMap類
HashMap和Hashtable類似,不同之處在於HashMap是非同步的,並且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。
WeakHashMap類
WeakHashMap是一種改進的HashMap,它對key實行「弱引用」,如果一個key不再被外部所引用,那麼該key可以被GC回收。
總結
如果涉及到堆棧,隊列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。
要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。
盡量返回介面而非實際的類型,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。
同步性
Vector是同步的。這個類中的一些方法保證了Vector中的對象是線程安全的。而ArrayList則是非同步的,因此ArrayList中的對象並不是線程安全的。因為同步的要求會影響執行的效率,所以如果你不需要線程安全的集合那麼使用ArrayList是一個很好的選擇,這樣可以避免由於同步帶來的不必要的性能開銷。
數據增長
從內部實現機制來講ArrayList和Vector都是使用數組(Array)來控制集合中的對象。當你向這兩種類型中增加元素的時候,如果元素的數目超出了內部數組目前的長度它們都需要擴展內部數組的長度,Vector預設情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最後你獲得的這個集合所佔的空間總是比你實際需要的要大。所以如果你要在集合中保存大量的數據那麼使用Vector有一些優勢,因為你可以通過設置集合的初始化大小來避免不必要的資源開銷。
使用模式
在ArrayList和Vector中,從一個指定的位置(通過索引)查找數據或是在集合的末尾增加、移除一個元素所花費的時間是一樣的,這個時間我們用O(1)表示。但是,如果在集合的其他位置增加或移除元素那麼花費的時間會呈線形增長:O(n-i),其中n代表集合中元素的個數,i代表元素增加或移除元素的索引位置。為什麼會這樣呢?以為在進行上述操作的時候集合中第i和第i個元素之後的所有元素都要執行位移的操作。這一切意味著什麼呢?
這意味著,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那麼使用Vector或ArrayList都可以。如果是其他操作,你最好選擇其他的集合操作類。比如,LinkList集合類在增加或移除集合中任何位置的元素所花費的時間都是一樣的?O(1),但它在索引一個元素的使用缺比較慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因為你可以簡單的使用索引來代替創建iterator對象的操作。LinkList也會為每個插入的元素創建對象,所有你要明白它也會帶來額外的開銷。
最後,在《Practical Java》一書中Peter Haggar建議使用一個簡單的數組(Array)來代替Vector或ArrayList。尤其是對於執行效率要求高的程序更應如此。因為使用數組(Array)避免了同步、額外的方法調用和不必要的重新分配空間的操作。
『拾』 Java中Collection和Collections的區別
淺談JAVA集合框架 Java提供了數種持有對象的方式,包括語言內置的Array,還有就是utilities中提供的容器類(container classes),又稱群集類(collection classes)。集合在java中非常重要,在討論之前,先來看幾個面試中的經典問題。 1 Collection 和 Collections的區別。 2 List, Set, Map是否繼承自Collection介面。 3 ArrayList和Vector的區別。 4 HashMap和Hashtable的區別。 篇尾有答案,我們開始正題。 集合Collection介面 --Collection 是任何對象組,元素各自獨立,通常擁有相同的套用規則。Set List由它派生。基本操作 增加元素add(Object obj); addAll(Collection c); 刪除元素 remove(Object obj); removeAll(Collection c); 求交集 retainAll(Collection c); 刪除元素 remove(Object obj); removeAll(Collection c); 求交集 retainAll(Collection c); 訪問/遍歷集合元素的好辦法是使用Iterator介面(迭代器用於取代Enumeration)Public interface Iterator{ Public Boolean hasNext(}; Public Object next(}; Public void remove(};} 集set --沒有重復項目的集合 有三種特定類型的集可用 HashSet-基於散列表的集,加進散列表的元素要實現hashCode()方法 LinkedHashSet-對集迭代時,按增加順序返回元素 TreeSet-基於(平衡)樹的數據結構 清單List --位置性集合。加進清單的元素可以加在清單中特定位置或加到末尾 有兩個特定版本ArrayList(數組表)-類似於Vector,都用於縮放數組維護集合。區別:一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的 二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半 LinkedList(鏈表)-是雙向鏈表,每個節點都有兩個指針指向上一節點和下一節點。 用在FIFO,用addList()加入元素 removeFirst()刪除元素用在FILO,用addFirst()/removeLast() ListIterator提供雙向遍歷next() previous(),可刪除、替換、增加元素 映射表Map --用於關鍵字/數值對,像個Dictionary 處理Map的三種集合 關鍵字集KeySet() 數值集value() 項目集enrySet() 四個具體版本HashMap-散列表的通用映射表 LinkedHashMap-擴展HashMap,對返回集合迭代時,維護插入順序 WeakHashMap-基於弱引用散列表的映射表,如果不保持映射表外的關鍵字的引用,則內存回收程序會回收它 TreeMap-基於平衡樹的映射表 HashMap-散列表的通用映射表 LinkedHashMap-擴展HashMap,對返回集合迭代時,維護插入順序 WeakHashMap-基於弱引用散列表的映射表,如果不保持映射表外的關鍵字的引用,則內存回收程序會回收它 TreeMap-基於平衡樹的映射表 Collections類,用於同步集合,還能改變集合只讀方式的類 e.g.:Map mp=new HashMap();mp=Collections.synchronizedMap(mp); //生成線程安全的映射表mp=Collections.unmodifiableMap(mp); //生成只讀映射表 Comparable 自然順序的排序類 Comparator 面向樹的集合排序類 容器分類學(Container taxonomy) 集合介面: Collection List Set;Map Iterator ListIterator。 抽象類: AbstractCollection AbstractList AbstractSet AbstractMap AbstractSequentiaList。老版本中的集合類型 Vector類 Vector,就是向量。一種異構的混合體,可以動態增加容量。對它的操作簡要如下 比如我們有一個Vector: Vector myVec=new Vector(a_Array.length) 取得vector的長度:myVec.size(); 賦值:set(int position,Object obj) / setElementAt(Object obj, int position) –不支持動態增長 add(Object obj )/ addElement(Object obj) 在Vector末尾加入對象 e.g.:myVec.add(new a_Array[0]); 取出元素:get(int position) / getElement(int position)Stack類 是Vector的子類。就是數據結構里講濫了的堆棧(這個詞可簡稱棧,不要混淆於heap-堆)。後進先出的存取方式。 Stack()構造空棧 Empty()叛空 Search()檢查堆棧是否有元素 Peek()取得棧頂元素 Pop()彈棧 Push()入棧 Enumeration介面 Dictionary類 字典。關鍵字/數值方式存取數據,如果映射沒有此關鍵字,取回null。Hashtable類 是Dictionary結構的具體實現。 面試題答案 Collection 和 Collections的區別。 Collections是個java.util下的類,它包含有各種有關集合操作的靜態方法。 Collection是個java.util下的介面,它是各種集合結構的父介面List, Set, Map是否繼承自Collection介面 List,Set是 Map不是 ArrayList和Vector的區別。 一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的 二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半 HashMap和Hashtable的區別 一.歷史原因:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map介面的一個實現 二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的 三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value