經常使用集合類簡介及線程安全和非線程安全的集合對象

簡介

Java中集合類有不少,只介紹經常使用的集合類:html

     

 線程安全和非線程安全的集合對象

1、概念:java

  • 線程安全:就是當多線程訪問時,採用了加鎖的機制;即當一個線程訪問該類的某個數據時,會對這個數據進行保護,其餘線程不能對其訪問,直到該線程讀取完以後,其餘線程纔可使用。防止出現數據不一致或者數據被污染的狀況。
  • 線程不安全:就是不提供數據訪問時的數據保護,多個線程可以同時操做某個數據,從而出現數據不一致或者數據污染的狀況。
  • 對於線程不安全的問題,通常會使用synchronized關鍵字加鎖同步控制。
  • 線程安全工做原理: jvm中有一個main memory對象,每個線程也有本身的working memory,一個線程對於一個變量variable進行操做的時候, 都須要在本身的working memory裏建立一個copy,操做完以後再寫入main memory。 當多個線程操做同一個變量variable,就可能出現不可預知的結果。
    而用synchronized的關鍵是創建一個監控monitor,這個monitor能夠是要修改的變量,也能夠是其餘本身認爲合適的對象(方法),而後經過給這個monitor加鎖來實現線程安全,每一個線程在得到這個鎖以後,要執行完加載load到working memory 到 use && 指派assign 到 存儲store 再到 main memory的過程。纔會釋放它獲得的鎖。這樣就實現了所謂的線程安全。

2、線程安全(Thread-safe)的集合對象:算法

  • Vector 線程安全:
  • HashTable 線程安全:
  • StringBuffer 線程安全:

3、非線程安全的集合對象:api

  • ArrayList :
  • LinkedList:
  • HashMap:
  • HashSet:
  • TreeMap:
  • TreeSet:
  • StringBulider:

4、相關集合對象比較:數組

Vector、ArrayList、LinkedList:
一、Vector:
     Vector與ArrayList同樣,也是經過數組實現的,不一樣的是它支持線程的同步,即某一時刻只有一個線程可以寫Vector,避免多線程同時寫而引發的不一致性,但實現同步須要很高的花費,所以,訪問它比訪問ArrayList慢。
二、ArrayList:
  a. 當操做是在一列數據的後面添加數據而不是在前面或者中間,並須要隨機地訪問其中的元素時,使用ArrayList性能比較好。
  b. ArrayList是最經常使用的List實現類,內部是經過數組實現的,它容許對元素進行快速隨機訪問。數組的缺點是每一個元素之間不能有間隔,當數組大小不知足時須要增長存儲能力,就要講已經有數組的數據複製到新的存儲空間中。當從ArrayList的中間位置插入或者刪除元素時,須要對數組進行復制、移動、代價比較高。所以,它適合隨機查找和遍歷,不適合插入和刪除。
三、LinkedList:
  a. 當對一列數據的前面或者中間執行添加或者刪除操做時,而且按照順序訪問其中的元素時,要使用LinkedList。
  b. LinkedList是用鏈表結構存儲數據的,很適合數據的動態插入和刪除,隨機訪問和遍歷速度比較慢。另外,他還提供了List接口中沒有定義的方法,專門用於操做表頭和表尾元素,能夠看成堆棧、隊列和雙向隊列使用。安全

Vector和ArrayList在使用上很是類似,均可以用來表示一組數量可變的對象應用的集合,而且能夠隨機的訪問其中的元素。數據結構

ArryList和LinkedList的區別:多線程

 

Vector與ArrayList比較:jvm

 1. 性能上
ide

  ArrayList底層數據結構是數組,適合隨機查找和遍歷,不適合插入和刪除,線程不安全,效率高。。LinkedList底層數據結構是鏈表, 適合數據的動態插入和刪除,隨機訪問和遍歷速度比較慢,線程不安全,效率高。。

 

  2. 同步性

 

    Vectors是可同步的,是線程安全的。ArrayList是不可同步的,不是線程安全的。因此, 通常單線程推薦用ArrayList,多線程中則用Vector 

 

 3. 數據增加

 

    往一個ArrayList或者Vector裏插入一個元素時,若是內部數組空間不夠,ArrayList或Vector會擴展它的大小。 Vector在默認狀況下增加一倍的大小,而ArrayList增長50%的大小。

 

 

HashTable、HashMap、HashSet:
     HashTable和HashMap採用的存儲機制是同樣的,不一樣的是:
一、HashMap:
a. 採用數組方式存儲key-value構成的Entry對象,無容量限制;
b. 基於key hash查找Entry對象存放到數組的位置,對於hash衝突採用鏈表的方式去解決;
c. 在插入元素時,可能會擴大數組的容量,在擴大容量時需要從新計算hash,並複製對象到新的數組中;
d. 是非線程安全的;
e. 遍歷使用的是Iterator迭代器;

二、HashTable:
a. 是線程安全的;
b. 不管是key仍是value都不容許有null值的存在;在HashTable中調用Put方法時,若是key爲null,直接拋出NullPointerException異常;
c. 遍歷使用的是Enumeration列舉;

三、HashSet:
a. 基於HashMap實現,無容量限制;
b. 是非線程安全的;
c. 不保證數據的有序

 

 

 

TreeSet、TreeMap:
    TreeSet和TreeMap都是徹底基於Map來實現的,而且都不支持get(index)來獲取指定位置的元素,須要遍從來獲取。另外,TreeSet還提供了一些排序方面的支持,例如傳入Comparator實現、descendingSet以及descendingIterator等。
一、TreeSet:
a. 基於TreeMap實現的,支持排序;
b. 是非線程安全的;

二、TreeMap:
a. 典型的基於紅黑樹的Map實現,所以它要求必定要有key比較的方法,要麼傳入Comparator比較器實現,要麼key對象實現Comparator接口;
b. 是非線程安全的;

 

Collection有兩個子接口:List和Set,兩者主要區別在於:list數據有序存放、可重複;set中數據無序存放,不可重複。

Vector

  Vector類實現了一個動態數組,主要用在事先不知道數組的大小,以及須要頻繁地進行查找,插入,刪除工做,或者只是須要一個能夠改變大小的數組的狀況。

建立:

Vector類支持4種構造方法。

第一種構造方法建立一個默認的向量,默認大小爲10:

Vector()

第二種構造方法建立指定大小的向量。

Vector(int size)

第三種構造方法建立指定大小的向量,而且增量用incr指定. 增量表示向量每次增長的元素數目(當該vector對象添加的元素接近原先分配的內存極限時,會以incr大小自動擴大該對象擁有的內存容量,以容納更多的數據)

Vector(int size,int incr)

第四中構造方法建立一個包含集合c元素的向量:利用父類對象建立子類對象

Vector(Collection c) 

  經常使用的vector操做方法:增、刪、查、改。

增:

vec.add(E element) 
將指定元素追加到此向量的末尾。 
vec.add(int index, E element) 
在此向量的指定位置插入指定的元素。 
vec.addAll(Collection c) 
將指定 Collection 中的全部元素按順序追加到此向量的末尾。 
vec.addAll(int index, Collection c) 
在指定位置將指定 Collection 中的全部元素插入到此向量中。

刪:

vec.remove(int index) 
移除此向量中指定位置的元素。 
vec.remove(value v) 
移除向量中元素值爲v的元素。
vec.removeAll(Collection c) 
今後向量中移除包含在集合c 中的全部元素。 
vec.removeAllElements() 
今後向量中移除所有組件,並將其大小設置爲零。 
vec.removeRange(int fromIndex, int toIndex) 
移除位於 fromIndex(包括)與 toIndex(不包括)之間的全部元素。

vec.clear() 移除全部元素。

查:

vec.get(int index)

返回向量中指定位置的元素。 
vex.indexOf(value v) 
返回v值在vec中的下標。
vec.isEmpty() 
檢查該向量是否爲空。 
vec.lastElement() 
返回此向量的最後一個元素。

int capacity() 
返回此向量的當前容量。

int size() 
返回此向量中的組件數。

String toString() 
返回此向量的字符串表示形式,其中包含每一個元素的 String 表示形式。 
改:

vec.set(int index, E element) 
用指定的元素替換此向量中指定位置處的元素。 
vex.setElementAt(E obj, int index) 
將此向量指定 index 處的組件設置爲指定的對象。 
vec.setSize(int newSize) 
設置此向量的大小。

ArrayList

ArrayList就是動態的數組,能夠動態的增長和減小元素,靈活的設置數組的大小。基本與Vector同樣。

建立:

 ArrayList提供了三個構造器:

public ArrayList(); 
默認的構造器,將會以默認(16)的大小來初始化內部的數組 
public ArrayList(Collection c); 
用一個集合對象來構造,並將該集合的元素添加到ArrayList 
public ArrayList(int n); 
用指定n的大小來初始化內部的數組.

增:

方法摘要
 boolean add(E e)
          將指定的元素添加到此列表的尾部。
 void add(int index, E element)
          將指定的元素插入此列表中的指定位置。
 boolean addAll(Collection<? extends E> c)
          按照指定 collection 的迭代器所返回的元素順序,將該 collection 中的全部元素添加到此列表的尾部。
 boolean addAll(int index, Collection<? extends E> c)
          從指定的位置開始,將指定 collection 中的全部元素插入到此列表中。

刪:

 E remove(int index)
          移除此列表中指定位置上的元素。
 boolean remove(Object o)
          移除此列表中首次出現的指定元素(若是存在)。
protected  void removeRange(int fromIndex, int toIndex)
          移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之間的全部元素。
void clear()
          移除此列表中的全部元素。

 

查: 

 E get(int index)
          返回此列表中指定位置上的元素。
 int indexOf(Object o)
          返回此列表中首次出現的指定元素的索引,或若是此列表不包含元素,則返回 -1。
 boolean isEmpty()
          若是此列表中沒有元素,則返回 true
int size()
          返回此列表中的元素數。
boolean contains(Object o)
          若是此列表中包含指定的元素,則返回 true

ArrayList支持3種遍歷方式

第一種,經過迭代器遍歷

Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
    value = (Integer)iter.next();
}

 第二種,隨機訪問,經過索引值去遍歷。

Integer value = null;for (int i=0; i<list.size(); i++) {
    value = (Integer)list.get(i);        
}

第三種,for-each遍歷

Integer value = null;
for (Integer integ:list) {
    value = integ;
}

改:

 E set(int index, E element)
          用指定的元素替代此列表中指定位置上的元素。

 

 Object[] toArray()
   

HashMap

這裏咱們先講hashmap,具體緣由等講到hashset的時候就知道了。

  HashMap基於哈希表的 Map 接口實現,以key-value的形式存在。在HashMap中,系統 key-value 當成一個總體進行處理,系統老是根據 Hash 算法來計算 key-value 的存儲位置,這樣能夠保證能快速存、取 Map 的 key-value 對。系統調用key的 hashCode() 方法獲得其 hashCode 值——每一個 Java 對象都有 hashCode() 方法,均可經過該方法得到它的 hashCode 值。獲得這個對象的 hashCode 值以後,系統會根據該 hashCode 值來決定key—value的存儲位置。
建立
構造方法摘要
HashMap() 
          構造一個具備默認初始容量 (16) 和默認加載因子 (0.75) 的空 HashMap
HashMap(int initialCapacity) 
          構造一個帶指定初始容量和默認加載因子 (0.75) 的空 HashMap
HashMap(int initialCapacity, float loadFactor) 
          構造一個帶指定初始容量和加載因子的空 HashMap
HashMap(Map<? extends K,? extends V> m) 
          構造一個映射關係與指定 Map 相同的 HashMap
 容量表示哈希表中桶的數量,初始容量是建立哈希表時的容量,加載因子是哈希表在其容量自動增長以前能夠達到多滿的一種尺度,它衡量的是一個散列表的空間的使用程度,負載因子越大表示散列表的裝填程度越高,反之愈小。
增:
V put(K key, V value) 
       插入鍵值對。
 void putAll(Map<? extends K,? extends V> m) 
          把map中的鍵值對插入到hashmap中。
刪:
 V remove(Object key) 
          若是此映射中存在該鍵的映射關係,則將其刪除。
 void

clear() 
          今後映射中移除全部映射關係。

 查:

 V get(Object key) 
          返回指定鍵在此標識哈希映射中所映射的值,若是對於此鍵來講,映射不包含任何映射關係,則返回 null

 

boolean isEmpty() 
          若是此映射不包含鍵-值映射關係,則返回 true
 Set<K> keySet() 
          返回此映射中所包含的鍵的 set 。//獲取hashmap中的key集合。
Collection<V> values() 
          返回此映射所包含的值的 collection 視圖。

 

 int size() 
          返回此映射中的鍵-值映射關係數。

 

 boolean containsKey(Object key) 
          若是此映射包含對於指定的鍵的映射關係,則返回 true
 boolean containsValue(Object value) 
          若是此映射將一個或多個鍵映射到指定值,則返回 true

HashSet

  HashSet是基於 HashMap 實現的,底層採用 HashMap 來保存數據。全部放入 HashSet 中的集合元素實際上由 HashMap 的 key 來保存,而 HashMap 的 value 則存儲了一個靜態的 Object 對象(向上轉型,這樣value就能夠是各類基本類型的值了)。HashSet 的絕大部分方法都是經過調用 HashMap 的方法來實現的,所以 HashSet 和 HashMap 兩個集合在實現本質上是相同的。 
建立:
HashSet hashSet = new HashSet();
HashSet hashset=new HashSet(collection);
增:
hashset.add(value);//向集合中添加一個元素
hashset.add(array[]);//把數組中的值添加到集合中
刪:

刪除一個元素:hashSet.remove(Object);

刪除全部元素:hashSet.clear();

查:

用迭代器遍歷:

Iterator it = hashSet.iterator();
  while(it.hasNext()){
   Object obj = it.next();

   而後針對obj進行一系列的操做,好比:輸出值、若是obj是類對象則調用屬性、方法。

}
 boolean contains(Object o)
          若是此 set 包含指定元素,則返回 true
 boolean isEmpty()
          若是此 set 不包含任何元素,則返回 true
 int size()
          返回此 set 中的元素的數量(set 的容量)。

 當從HashSet中訪問元素時,HashSet先計算該元素的hashCode值(也就是調用該對象的hashCode())方法的返回值),而後直接到該hashCode對應的位置去取出該元素。  爲了保證HashSet能正常工做,要求當兩個對象用equals比較相等時,hashCode也要相等,不然就會有可能加入兩個相同的項。

HashSet的特色:

(1)HashSet不是同步的,多個線程訪問是須要經過代碼保證同步

(2)集合元素值能夠爲null。

相關文章
相關標籤/搜索