List,Set,Map用法以及區別(轉)


Collection是最基本的集合接口,一個Collection表明一組Object,即Collection的元素。一些Collection容許相同的元素而另外一些不行。一些能排序而另外一些不行。Java JDK不能提供直接繼承自Collection的類,Java JDK提供的類都是繼承自Collection的"子接口",如:List和Set。 

注意:Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同key,每一個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容能夠被當作一組key集合,一組value集合,或者一組key-value映射。 


詳細介紹: 
List特色:元素有放入順序,元素可重複 
Map特色:元素按鍵值對存儲,無放入順序 
Set特色:元素無放入順序,元素不可重複(注意:元素雖然無放入順序,可是元素在set中的位置是有該元素的HashCode決定的,其位置實際上是固定的) 
List接口有三個實現類:LinkedList,ArrayList,Vector 
LinkedList:底層基於鏈表實現,鏈表內存是散亂的,每個元素存儲自己內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢 
ArrayList和Vector的區別:ArrayList是非線程安全的,效率高;Vector是基於線程安全的,效率低 
Set接口有兩個實現類:HashSet(底層由HashMap實現),LinkedHashSet 
SortedSet接口有一個實現類:TreeSet(底層由平衡二叉樹實現) 
Query接口有一個實現類:LinkList 
Map接口有三個實現類:HashMap,HashTable,LinkeHashMap 
  HashMap非線程安全,高效,支持null;HashTable線程安全,低效,不支持null 
SortedMap有一個實現類:TreeMap 
其實最主要的是,list是用來處理序列的,而set是用來處理集的。Map是知道的,存儲的是鍵值對 
set 通常無序不重複.map kv 結構 list 有序 html

Java複習筆記——容器知識點總結java

Java中容器分兩類,一種是單值的Collection,一種是儲存鍵-值對的Map算法

 

Collection數組

又分兩種,Set和List,區別在於Set是不可重複的,而List是可重複的安全

Set微信

經常使用有兩種:HashSet和TreeSet,其內部實現是一個Map,它的元素就至關於Map中的Key,而Value是一個Object常量this

 

?
1
2
3
4
5
6
7
private transient HashMap<E,Object> map;
 
private static final Object PRESENT = new Object();
 
public HashSet() {
     map = new HashMap<E,Object>();
}

 

?
1
2
3
4
5
6
7
private transient NavigableMap<E,Object> m;
 
private static final Object PRESENT = new Object();
 
public TreeSet() {
     this ( new TreeMap<E,Object>());
}

 

全部對Set的操做都被最終轉嫁爲對Map的操做,具體細節在下面Map中講述編碼

 

Listspa

對Collection接口進行了簡單的擴充,你能夠將任何對象放到放到一個List容器中,並在須要時從中取出。線程

經常使用的有ArrayList和LinkedList,都是有順序,可重複的集合類型

 

ArrayList:顧名思義,數據列表,其實就是封裝了一個數組,所以它的訪問速度極快

 

?
1
2
3
private transient Object[] elementData;
 
private int size;

而後封裝了一些對數組的經常使用操做如插入、刪除等。

 

說到ArrayList不得不提下Arrays類和數組[]

ArrayList能夠儲存不一樣類型的對象(雖然通常不推薦這樣作),而數組只能是同一類型

ArrayList能夠動態增長長度,但效率不高,而數組只能是固定長度,卻十分高效。每當執行add/insert等添加元素的方法,都會先檢查數組長度是否足夠,若是是,它就會以當前容量的3/2倍+1來從新構建一個數組,將舊元素Copy到新數組中,而後丟棄舊數組,在這個臨界點的擴容操做,應該來講是比較影響效率的。

ArrayList提供經常使用方法,add/get/indexOf/remove等,而相應的Arrays沒有提供add和remove方法,查詢元素索引要先sort再binarySearch

ArrayList排序需外部方法Collections.sort(..),數組排序則使用Arrays.sort(..),兩者均可以使用天然順序(實現Comparable)或用Comparator指定

 

LinkedList:很顯然的是鏈表,內部實現是帶頭結點的雙向鏈表,適合於在鏈表中間須要頻繁進行插入和刪除操做

 

?
1
2
3
4
5
6
7
8
9
10
11
12
private transient Entry<E> header = new Entry<E>( null , null , null );
 
private transient int size = 0 ;
 
private static class Entry<E> {
 
     E element;
     Entry<E> next;
     Entry<E> previous;
 
//..
}

 

 

Map

是一種把鍵和值對象進行關聯的容器,類比Collection,能夠這樣說:Collection對象中某個值的ID是它在容器中的索引值,而在Map中,某個值的ID是它對應的鍵。這樣咱們使用Map時就不用侷限於int型的索引值,能夠用任何類型的對象做索引。正是因爲Key的索引特性,Map中不容許有同值的Key存在(前文講到Set內部實現是Map中的Key的集合,因此Set的元素不能重複)。固然,Value是能夠重複的,甚至能夠是同一個Reference。Map在處理相同的Key時,將新值存入,舊值被替換並返回

 

HashMap採用Hash算法,以便快速查找某個元素。

將鍵的哈希值做爲內存索引依據,內部實現是一個適當長度的鏈式數組,由Key的Hash值對應數組下標,再間接對應內存,是一種比較高效的存取方式。Key的hashCode()相同的狀況下,放在同一個單項鍊表結構中。

一個HashMap中Key的類型應該重寫hashCode()方法,保證在兩個對象equals爲true時返回相同的值,不然在重複性檢查時會直接被當作不一樣的鍵,形成不可預期的後果。

Hash容器中判斷重複的方式:

先比較hash(key.hashCode())是否相同,hash(int)是一個內部算法,具體細節不做討論

  不一樣,則不重複

  相同,則

    比較兩個Key是不是同一引用

      是,則重複

      不是,再調用equals方法

        返回true則重複

        返回false則不重複

TreeMap:採用樹型儲存結構按序存放,所以它便有一些擴展的方法,好比firstKey(),lastKey()等,你還能夠從TreeMap中指定一個範圍以取得其子Map。

內部實現是一顆二叉排序樹,其中序遍歷結果爲遞增序列。因此要求他的Key必須是Comparable或者建立TreeMap的時候指定Comparator。

當Key實現Comparable<E>接口時,必須實現comparaTo(E e)方法,當使用外部比較器(Comparator<T>)時,需實現Comparator<T>的compare(T t1, T t2)方法

 

相關知識

 

泛型(Generic)

泛型容許Coding的時候能夠定義一些可變的類型,但必須在使用前進行聲明具體是哪一種類型

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class testGeneric<T> {
     T t;
     testGeneric(T t) {
         this .t = t;
     }
}
 
class test {
     testGeneric<String> tgs = new testGeneric( "Hi,Gineric!" );
     testGeneric<Integer> tgi = new testGeneric( 100 ); //AutoBoxing
     {
         System.out.println(tgs.t); //Output:Hi,Gineric!
         System.out.println(tgi.t); //AutoUnBoxing&Output:100
     }
}

須要注意Java 泛型的類型參數之實際類型在編譯時會被消除(upcast to Object),因此沒法在運行時得知其類型參數的類型。Java 編譯器在編譯泛型時會自動加入類型轉換的編碼,故運行速度不會由於使用泛型而加快。

 

迭代器(Iterator)

提供一種方法訪問一個容器(container)對象中各個元素,而又不需暴露該對象的內部細節。

對於遍歷一個容器中全部的元素,Iterator模式是首選的方式

Collection定義了Iterator<E> iterator()方法,子類都各自實現了該方法,咱們直接調用便可

Map中雖沒有定義,咱們能夠利用map.entrySet()的iterator()方法

 

?
1
2
3
4
5
6
7
Iterator i = someMap.entrySet().iterator();
while (i.hasNext()) {
     Map.Entry entry = (Map.Entry) i.next();
     Object key = i.getKey();
     Object value = i.getValue();
     //something TODO
}

或者轉換爲Collection(Set)用加強For循環

 

?
1
2
3
4
5
6
Set<Map.Entry> entrySet = someMap.entrySet();
for (Map.Entry entry : entrySet){
     Object key = entry.getKey();
     Object value = entry.getValue();
     //something TODO
}

 

ListIterator繼承了Iterator,提供了對List的雙向遍歷的方法。

須要注意的是,調用Iterator的remove方法,刪除的是最後一次調用next()(or previous(),if possible)所返回的元素

若是進行迭代時用調用此方法以外的其餘方式修改了該迭代器所指向的 collection,則迭代器的行爲是不肯定的。

也就是說,調用Iterator時,最好不要調用Collection的add/remove等方法

另:容器類的toString()方法也是經過調用iterator()方法來實現遍歷

  對集合使用加強的for循環也是隱式地調用iterator()方法

轉自:http://mingcn.cnblogs.com/archive/2010/10/22/JavaContainer.html

關注微信公衆號得到更多內容:

                                                            

相關文章
相關標籤/搜索