简体   繁体   English

为什么没有针对 ConcurrentHashMap 的 ConcurrentHashSet

[英]Why there is no ConcurrentHashSet against ConcurrentHashMap

HashSet is based on HashMap. HashSet 基于 HashMap。

If we look at HashSet<E> implementation, everything is been managed under HashMap<E,Object> .如果我们看一下HashSet<E>的实现,一切都在HashMap<E,Object>下进行管理。

<E> is used as a key of HashMap . <E>用作HashMap的密钥。

And we know that HashMap is not thread safe.而且我们知道HashMap不是线程安全的。 That is why we have ConcurrentHashMap in Java.这就是为什么我们在 Java 中有ConcurrentHashMap

Based on this, I am confused that why we don't have a ConcurrentHashSet which should be based on the ConcurrentHashMap ?基于此,我很困惑为什么我们没有应该基于 ConcurrentHashMap 的ConcurrentHashMap

Is there anything else that I am missing?还有什么我想念的吗? I need to use Set in a multi-threaded environment.我需要在多线程环境中使用Set

Also, If I want to create my own ConcurrentHashSet can I achieve it by just replacing the HashMap to ConcurrentHashMap and leaving the rest as is?另外,如果我想创建自己的ConcurrentHashSet ,我可以通过将HashMap替换为ConcurrentHashMap并将 rest 保持原样来实现吗?

There's no built in type for ConcurrentHashSet because you can always derive a set from a map. ConcurrentHashSet没有内置类型,因为您总是可以从地图派生一个集合。 Since there are many types of maps, you use a method to produce a set from a given map (or map class). 由于有许多类型的地图,因此您可以使用方法从给定地图(或地图类)生成集合。

Prior to Java 8, you produce a concurrent hash set backed by a concurrent hash map, by using Collections.newSetFromMap(map) 在Java 8之前,通过使用Collections.newSetFromMap(map)生成由并发哈希映射支持的并发哈希Collections.newSetFromMap(map)

In Java 8 (pointed out by @Matt), you can get a concurrent hash set view via ConcurrentHashMap.newKeySet() . 在Java 8(由@Matt指出)中,您可以通过ConcurrentHashMap.newKeySet()获得并发哈希集视图 This is a bit simpler than the old newSetFromMap which required you to pass in an empty map object. 这比旧的newSetFromMap要简单得多,后者要求你传入一个空的地图对象。 But it is specific to ConcurrentHashMap . 但它特定于ConcurrentHashMap

Anyway, the Java designers could have created a new set interface every time a new map interface was created, but that pattern would be impossible to enforce when third parties create their own maps. 无论如何,每次创建新的地图界面时,Java设计者都可以创建一个新的集合界面,但是当第三方创建自己的地图时,该模式将无法实施。 It is better to have the static methods that derive new sets; 最好使用派生新集的静态方法; that approach always works, even when you create your own map implementations. 即使您创建自己的地图实现,该方法也始终有效。

Set<String> mySet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());

使用Guava 15,您还可以使用:

Set s = Sets.newConcurrentHashSet();

就像Ray Toal所提到的那样简单:

Set<String> myConcurrentSet = ConcurrentHashMap.newKeySet();

It looks like Java provides a concurrent Set implementation with its ConcurrentSkipListSet . 看起来Java提供了ConcurrentSkipListSet的并发Set实现。 A SkipList Set is just a special kind of set implementation. SkipList Set只是一种特殊的集合实现。 It still implements the Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet interfaces. 它仍然实现Serializable,Cloneable,Iterable,Collection,NavigableSet,Set,SortedSet接口。 This might work for you if you only need the Set interface. 如果您只需要Set接口,这可能对您有用。

As pointed by this the best way to obtain a concurrency-able HashSet is by means of Collections.synchronizedSet() 正如指出由 ,获得并发能够HashSet的最好的办法是借助于Collections.synchronizedSet()

Set s = Collections.synchronizedSet(new HashSet(...));

This worked for me and I haven't seen anybody really pointing to it. 这对我有用,我没有看到任何人真正指向它。

EDIT This is less efficient than the currently aproved solution, as Eugene points out, since it just wraps your set into a synchronized decorator, while a ConcurrentHashMap actually implements low-level concurrency and it can back your Set just as fine. 编辑这比当前被批准的解决方案效率低,正如Eugene所指出的那样,因为它只是将你的集合包装成一个同步的装饰器,而ConcurrentHashMap实际上实现了低级别的并发性,它可以支持你的Set一样好。 So thanks to Mr. Stepanenkov for making that clear. 所以感谢Stepanenkov先生说清楚了。

http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set- http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedSet-java.util.Set-

You can use guava's Sets.newSetFromMap(map) to get one. 您可以使用guava的Sets.newSetFromMap(map)来获取一个。 Java 6 also has that method in java.util.Collections Java 6在java.util.Collections也有该方法

import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


public class ConcurrentHashSet<E> extends AbstractSet<E> implements Set<E>{
   private final ConcurrentMap<E, Object> theMap;

   private static final Object dummy = new Object();

   public ConcurrentHashSet(){
      theMap = new ConcurrentHashMap<E, Object>();
   }

   @Override
   public int size() {
      return theMap.size();
   }

   @Override
   public Iterator<E> iterator(){
      return theMap.keySet().iterator();
   }

   @Override
   public boolean isEmpty(){
      return theMap.isEmpty();
   }

   @Override
   public boolean add(final E o){
      return theMap.put(o, ConcurrentHashSet.dummy) == null;
   }

   @Override
   public boolean contains(final Object o){
      return theMap.containsKey(o);
   }

   @Override
   public void clear(){
      theMap.clear();
   }

   @Override
   public boolean remove(final Object o){
      return theMap.remove(o) == ConcurrentHashSet.dummy;
   }

   public boolean addIfAbsent(final E o){
      Object obj = theMap.putIfAbsent(o, ConcurrentHashSet.dummy);
      return obj == null;
   }
}

为什么不使用:java.util.concurrent中的CopyOnWriteArraySet?

We have ConcurrentHashSet in io.vertx which can be used against java.util ConcurrentHashMap.我们在 io.vertx 中有 ConcurrentHashSet,它可以用于 java.util ConcurrentHashMap。 https://www.javadoc.io/static/io.vertx/vertx-core/3.0.0/io/vertx/core/impl/ConcurrentHashSet.html https://www.javadoc.io/static/io.vertx/vertx-core/3.0.0/io/vertx/core/impl/ConcurrentHashSet.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM