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


簡介

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的過程。才會釋放它得到的鎖。這樣就實現了所謂的線程安全。

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

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

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

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

四、相關集合對象比較:

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

Vector和ArrayList在使用上非常相似,都可以用來表示一組數量可變的對象應用的集合,並且可以隨機的訪問其中的元素。

ArryList和LinkedList的區別:

 

Vector與ArrayList比較:

 1. 性能上

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

 

  2. 同步性

 

    Vectors是可同步的,是線程安全的。ArrayList是不可同步的,不是線程安全的。所以, 一般單線程推薦用ArrayList,多線程中則用Vector 

 

 3. 數據增長

 

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

 

 

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

2、HashTable:
a. 是線程安全的;
b. 無論是key還是value都不允許有null值的存在;在HashTable中調用Put方法時,如果key為null,直接拋出NullPointerException異常;
c. 遍歷使用的是Enumeration列舉;

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

 

 

 

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

2、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。


免責聲明!

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



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