Java 容器(list, set, map)


java容器類庫的簡化圖:

(虛線框表示接口, 實線框表示普通的類,

空心箭頭表示特定的類實現了接口, 實心箭頭表示某個類可以生成箭頭所指的類對象)

image

 

繼承Collection的主要有Set 和 List.

 

List:

ArrayList    內部實現是用數組, 隨機訪問速度快, 刪除或插入元素速度慢。

LinkedList  內部實現是用鏈表, 隨機訪問速度慢,刪除和插入元素相對較快。

平時最佳的做法可能是將ArrayList作為默認首選,只有你需要使用額外的功能,或者因為經常從表中插入或刪除元素導致程序性能變差的時候,才去選擇LinkedList。

Vector和Stack是過去遺留下來的類,目的只是為了支持老程序,應該在編寫程序時盡量避免使用它們。

 

Set:

Hash

HashSet: 為快速查找而設計,可以認為是基於哈希表的實現。 存入HashSet的元素必須定義hashCode().

LinkedHashSet: 具有HashSet的查詢速度且內部使用鏈表維護元素的順序(按插入的順序或最近最少使用順序)

 

Tree

TreeSet:保持次序的Set,底層為樹結構(紅黑樹)。使用它可以從Set提取有序的序列。元素必須實現Comparable接口或者在構造TreeSet時傳入Comparator參數。

 

 1 class Stone {
 2     private int volume;
 3 
 4     public Stone(int volume) {
 5         this.volume = volume;
 6     }
 7 
 8     public int getVolume() {
 9         return volume;
10     }
11 
12     //...........省略..........//
13 }
14 
15 class Stick implements Comparable{
16     private int length;
17 
18     public Stick(int length) {
19         this.length = length;
20     }
21 
22     public int getLength() {
23         return length;
24     }
25 
26     @Override
27     public int compareTo(Object o) {
28         Stick st = (Stick)o;
29         return this.getLength() - st.getLength();
30     }
31 
32     //...........省略..........//
33 }
34 
35 public class MyComparator implements Comparator<Stone>{
36 
37     @Override
38     public int compare(Stone st1, Stone st2) {
39         return st1.getVolume() - st2.getVolume();
40     }
41 
42     public static void main(String[] args) {
43         new TreeSet<Stone>(new MyComparator()); //傳入Comparator
44 
45         new TreeSet<Stick>(); //Stick實現了Comparable
46     }
47 }
View Code

 

 

不管是散列存儲還是樹形存儲,元素都必須實現equals()方法雖然只有當時被放入HashSet或LinkedHashSet是hashCode()才是必須的,但是,對於良好的編程風格,應該在覆蓋equals()方法的同時也覆蓋hashCode()方法。

 

equals()方法必須滿足5個條件:

1. 自反性。 對任意x,    x.equals(x)一定為true

2. 對稱性。 對任意x、y,     如果y.equals(x)為true, x.equals(y)也為true

3. 傳遞性。 對任意x、y、z, 如果x.equals(y), y.equals(z)都為true, x.equals(z)也應該為true

4. 一致性。 對任意x、y,   如果對象中用於等價比較的信息沒有改變,那么無論調用x.equals(y)多少次,其返回結果都應該一致。

5. 對於任何不是null的x,     x.equals(null)一定為false

 

hashCode()的編寫建議(Effective Java):

1. 給result(int型)一個非零的初始值

2. 為對象內每個有意義的域f(即每個可以做equals()操作的域)計算出一個int散列碼c

域類型

計算

boolean c = ( f ? 0 : 1)

byte, char, short, 或 int

c = (int)f
long c = (int)(f ^ (f>>>32))
float c = Float.floatToIntBits(f);
double

long l = Double.doubleToLongBits(f);
c = (int)(1 ^ (l>>>32))

Object

c = f.hashCode( )
Array 對數組中的每個元素應用上述規則

 

3. 合並計算得到的散列碼 result = 37 * result + c

4. 返回 result

5. 檢查hashCode()最后生成的結果,確保相同的對象有相同的散列碼

 

 

SortedSet(接口)保證元素處於排序狀態(按對象的比較函數對元素排序),主要方法有:

Comparator comparator()  返回當前Set使用的Comparator,如果返回空,表示以自然排序(即按元素實現的Comparable中

                                     compareTo()方法排序)。

Object first() 返回容器的第一個元素

Object last() 返回容器的最后一個元素

SortedSet subSet(fromElement, toElement) 生成此Set的子集,范圍從fromElement(包含)到toElement(不包含)

SortedSet headSet(toElement) 生成此Set的子集,由小於toElement的元素組成

SortedSet tailSet(fromElement) 生成此Set的子集,有大於等於fromElement的元素組成

 

TreeSet實現SortedSet,包括SortedSet的方法。

 

 

可選操作

在Collection接口中執行各種添加和移除的方法都是可選的。也就是說實現Collection接口的類並不需要為這些方法提供有意義的功能實現。這違反了面向對象設計中的規則(無論你選擇如何實現接口,應該保證能夠向該接口發送這些消息)。

可選操作聲明調用某些方法將不會執行有意義的行為,相反,它們會拋出異常。

可選操作是邏輯上的,在實現接口時,還是需要覆蓋接口所謂的可選方法,只不過你不一定要提供有意義的實現,如果不支持該可選方法,可以在該方法出拋出UnsupportedOperationException。

 

那么為什么需要將方法定義為可選呢?

這樣可以防止設計中出現接口過多的情況。

比如現在有下面三種需求(當然可以有更多不同的需求)

不能修改集合內容的容器,

只能添加元素的容器,

只能刪除元素的容器。

那么現在就需要為上面三種需求各定義一種接口,顯然這樣比起現在的Collection,需要定義更多的接口。這樣會導致接口過多,使整個容器類庫更加復雜。

注意:UnsupportedOperationException必須是一個罕見的異常。即對大多數類來說,所有操作都應該可以工作,只有在特列中才會有未獲得支持的操作。

 

快速報錯(fail-fast)

java容器有一種保護機制,能夠防止多個進程同時修改同一容器的內容。

如果在迭代遍歷某個容器的過程中,另一個進程介入其中,並且插入、刪除或修改此容器內的某個對象,那么就容易出現問題。

java容器類類庫采用fail-fast機制。他會探查容器上除了當前線程所進行的操作之外的所有變化,一旦發現其它進程修改了容器,就會立刻拋出ConcurrentModificationException異常。

示例:

 1 import java.util.*;
 2 public class FailFast {
 3     public static void main(String[] args) {
 4         Collection<String> c = new ArrayList<String>();
 5         Iterator<String> it = c.iterator();
 6         c.add("An object");
 7         try {
 8             String s = it.next();
 9         } catch(ConcurrentModificationException e) {
10             System.out.println(e);
11         }
12     }
13 } 
14 /* Output:
15 java.util.ConcurrentModificationException
16 *///:~
View Code

 

Map

HashMap  基於散列表的實現(它取代了HashTable, HashTable是過時的類)。

LinkedHashMap 類似與HashMap, 但是迭代遍歷時,取得“鍵值對”的順序是其插入的順序

                       或最近最少使用的順序(如果在構造LiskedHashMap傳入參數accessOrder=true)。

                        比HashMap慢一點,但是在迭代訪問時更快,因為它使用鏈表維護內部的次序。

TreeMap 基於紅黑樹的實現。查看key 或 key-value是,它們會被排序(次序由Comparator或Comparable決定)

 

 

博客園(FOREVER_ENJOY):http://www.cnblogs.com/zyx1314/p/5331282.html

本文版權歸作者所有;歡迎轉載!請注明文章作者和原文連接


免責聲明!

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



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