ConcurrentHashMap.newKeySet() 对比 Collections.newSetFromMap()

ConcurrentHashMap.newKeySet() vs Collections.newSetFromMap()

Java 8引入了获得并发的新方法Set实现

// Pre-Java-8 way to create a concurrent set
Set<String> oldStyle = Collections.newSetFromMap(new ConcurrentHashMap<>());
// New method in Java 8
Set<String> newStyle = ConcurrentHashMap.newKeySet();

有什么理由更喜欢新方法吗?

任何advantages/disadvantages?

ConcurrentHashMap.newKeySet() 应该更有效一些,因为删除了一个间接级别。 Collections.newSetFromMap(map) 主要是基于将操作重定向到 map.keySet(),但是 ConcurrentHashMap.newKeySet() 非常接近 map.keySet() 本身(只是增加了支持)。

至于功能,我看不出有什么不同。

ConcurrentHashMap.newKeySet() 只是比 Collections.newSetFromMap(new ConcurrentHashMap<>()).

更广泛的功能的一部分

如果您看一下这个例子,区别就很明显了:

Set<String> set=new ConcurrentHashMap<String,String>().keySet("hello");

在向 Set.

添加新值时,您现在添加值 "hello" 而不是映射到 Boolean.TRUE

这就是返回的 Set 类型为 ConcurrentHashMap.KeySetView. This type has additional methods for asking for the backing map as well as which value will be used when adding new keys 的原因。


所以虽然 ConcurrentHashMap.newKeySet() 看起来和 Collections.newSetFromMap(new ConcurrentHashMap<>()) 做的一样,但语义上的差异是后者说你之后不应该使用地图,而前者是一个功能的一部分旨在与地图互动。

参见Collections.newSetFromMap:

The specified map must be empty at the time this method is invoked, and should not be accessed directly after this method returns.

事实上,甚至没有指定 Collections.newSetFromMap 将使用 Boolean.TRUE 作为附加值——无论如何你都不应该处理它……


当您想将 Set 传递给明确请求 ConcurrentHashMap.KeySetView 的代码时,它也可能很有用。


如果您仅使用编译时类型 Set 使用结果,接收 Set 的代码仍有可能使用 instanceof/type 转换为发现 ConcurrentHashMap.newKeySet() 的结果由 ConcurrentHashMap 支持,而 Collections.newSetFromMap 的结果不会告诉你。另一方面,这也允许代码以这种方式使用支持映射做意想不到的事情……