在JDK 8以前,沒法在Java中建立大型,線程安全的ConcurrentHashSet。該java.util.concurrent包沒有一個叫作ConcurrentHashSet的類,可是從JDK 8開始,可使用新添加的keySet(默認值)和newKeySet()方法在Java中建立一個由ConcurrentHashMap支持的ConcurrentHashSet。這比舊的解決方案更好。keySet(defaultValue)和newKeySet()返回的SetJDK 8的方法是一個合適的集合,還能夠添加新元素以及執行其餘集合操做,例如contains(),remove()等。java
這些方法只能在ConcurrentHashMap類中使用而不能在ConcurrentMap接口中使用,因此須要使用ConcurrentHashMap 引用變量來保存引用,或者可使用類型轉換來轉換ConcurrentHashMap對象存儲在ConcurrentMap變量中。程序員
Java Concurrency API具備流行Collection類的併發版本,例如用於ArrayList的CopyOnArrayList,用於HashMap的ConcurrentHahsMap和用於HashSet的CopyOnWriteArraySet,但沒有Java中的ConcurrentHashSet。 即便CopyOnWriteArraySet的線程安全,它也不適合大型線程安全集的應用程序。它僅用於設置大小保持較小且只讀操做數量遠遠超過寫入操做的應用程序。 因此,當你向Java程序員詢問如何建立ConcurrentHashSet時,沒有編寫本身的類,不少人會說他們可使用具備相同值的ConcurrentHashMap。事實上,這也是Java建立HashSet的方法。數組
可是,這種方法的問題是隻有一個map而沒有set,它不能使用虛擬值對ConcurrentHashMap執行set操做。當某些方法須要Set時,你不能傳遞它,所以它不是頗有用。安全
另外一個選項是,許多Java程序員會提到,能夠經過調用keySet()方法從ConcurrentHashMap得到一個Set視圖,而keySet()方法實際上返回一個Set,也能夠在其中執行Set操做,並將其傳遞給一個須要Set的方法,但這種方法也有其侷限性。也將反映在Set中。另外一個限制是沒法在此鍵集中添加新元素,這樣作會拋出UnsupportedOperationException。併發
與keySet()方法返回的Set視圖不一樣,還能夠將新對象添加到此Set中。該方法也被重載並接受初始容量以防止Set的大小調整。app
1.1使用newKeySet()的ConcurrentHashSetspa
建立ConcurrentHashSet的代碼示例:線程
ConcurrentHashMap<String,Integer> certificationCosts = new ConcurrentHashMap<>();
Set<String> concurrentHashSet = certificationCosts.newKeySet();
concurrentHashSet.add("OCEJWCD"); //OK
concurrentHashSet.contains("OCEJWCD"); //OK
concurrentHashSet.remove("OCEJWCD"); //OK
複製代碼
這不是在Java中建立併發,大型,線程安全的Set 的惟一方法。code
還可使用新添加的keySet(默認值)方法來建立ConcurrentHashSet。此方法返回ConcurrentHashMap中鍵的Set視圖,使用添加的給定公共默認值(即Collection.add()和Collection.addAll(Collection))。cdn
1.2使用keySet的ConcurrentHashSet(默認值)
如下是使用keySet(映射值)方法獲取ConcurrentHashSet的示例:
ConcurrentHashMap<String, Integer> certificationCosts = new ConcurrentHashMap<>();
Set<String>concurrentHashSet = certificationCosts.keySet(246);
concurrentSet.add("Spring enterprise"); // 值爲246
複製代碼
你也能夠用這個Set 執行其餘Set操做,例如addAll(),remove(),removeAll(),retainAll(),contains()。
這是我使用java.util.concurrent.ConcurrentHashMap類中添加的新方法建立的大型,線程安全的併發集的完整的程序。
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/*
* 從Map中刪除鍵值對的程序
* 迭代
*/
public class Demo {
public static void main(String[] args) throws Exception {
ConcurrentHashMap certificationCosts = new ConcurrentHashMap<>();
certificationCosts.put("OCAJP", 246);
certificationCosts.put("OCPJP", 246);
certificationCosts.put("Spring Core", 200);
certificationCosts.put("Spring Web", 200);
certificationCosts.put("OCMJEA", 300);
Set concurrentSet = certificationCosts.keySet();
System.out.println("before adding element into concurrent set: " + concurrentSet);
// concurrentSet.add("OCEJWCD");
// 將拋出UnsupportedOperationExcetpion System.out.println("after adding element into concurrent set: " + concurrentSet);
// 使用newKeySet()方法 Set 在Java 8中建立併發哈希集
concurrentHashSet = certificationCosts 。newKeySet();
concurrentHashSet.add("OCEJWCD");
concurrentHashSet.contains("OCEJWCD");
concurrentHashSet.remove("OCEJWCD");
System.out.println("after adding element into concurrent HashSet:" + concurrentSet);
// 可使用keySet(defaultValue)方法將元素添加到Set
concurrentSet = certificationCosts.keySet(246);
concurrentSet.add("Spring enterprise");
// 值是246
}
}
Output
before adding an element into the concurrent set:
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]
after adding an element into the concurrent set:
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]
after adding an element into concurrent HashSet:
[Spring Web, OCPJP, OCAJP, Spring Core, OCMJEA]
複製代碼
能夠看到,若是嘗試向ConcurrentHashMap的keySet()方法返回的Set中添加新對象,它會拋出UnsupportedOperationExcepiton,以下所示: java.util.concurrent.ConcurrentHashMap $ 中線程「main」中的異常java.lang.UnsupportedOperationException Demo.main中的KeySetView.add(ConcurrentHashMap.java:4594) (Demo.java:23)
這就是我註釋代碼的緣由,可是,由newKeySet()和keySet(mapping value)方法返回的Set容許向集合中添加新元素,這裏沒有錯誤。
順便說一下,這不是在Java中建立線程安全集的惟一方法。
如下是CopyOnWriteArraySet的一些重要屬性:
1。它最適合於很小的應用程序,只讀操做數量遠遠超過可變操做,而且須要在遍歷期間防止線程之間的干擾。
2.它的線程是安全的。
rators不支持可變刪除操做。
經過迭代器的遍歷速度很快,不會遇到來自其餘線程的干擾。
rators在構建迭代器時可以保持數組的快照不變。
這就是如何在Java 8中建立ConcurrentHashSet。