Guava的ImmutableSet成员资格方法是否模仿java.util.HashSet#contains?

时间:2015-02-08 07:01:24

标签: java set guava hashset

我需要确保我创建的某个Set<String>不会在代码中的其他位置修改。当然,我最终使用了番石榴ImmutableSet

这个不可变集非常大(大约59K字符串),每次调用特定方法时我都必须执行Set#contains检查。所以我想知道是否有任何方法可以指定大集合中的查找。 Guava的文档说:

  

具有可靠性,用户指定的高性能,不可变集   迭代顺序。不允许使用null元素。

如果通过调用user-specified iteration创建了不可变集合,ImmutableSet#copyOf(aHashSet)意味着什么?如果我使用contains(String)代替ImmutableSet#containsHashSet#contains的效果会受到不利影响吗?更确切地说,我的问题如下:

使用相当好的哈希函数并且没有太多元素进入同一个存储桶,人们会期望HashSet#contains为O(1)。使用copyOf创建的ImmutableSet是否会遵守此内容?

我怀疑有两个原因可能并非如此:

  1. Guava forum discussion on precisely this question(虽然似乎无法提供确凿的答案)。

  2. 我不清楚ImmutableSet#contains是否遵从java.util.Set#contains(即HashSet中的实施,在我的情况下)或com.google.common.collect.ImmutableCollection#contains 。如果是后者,则ImmutableSet#contains将是O(n)操作。

2 个答案:

答案 0 :(得分:3)

我在the documentation中看到的唯一确认如下:

  

此类的工厂方法创建基于哈希的实例,...

换句话说,您可以期望查找使用类似于HashSet的散列机制(因此具有性能特征)。文档是故意模糊的,因此可以进行各种改进(例如,对某些特殊情况使用特殊实现,如单例或空集)。

迭代顺序取决于创建方法。在copyOf的情况下,它将是您传入的Iterable的迭代顺序(当然,在复制时)。这有很好的记录:

  

按顺序返回包含给定元素的不可变集合。

至于它是否遵循set的contains方法,没有。由于ImmutableSet制作副本(与Collections.unmodifiableSet()不同),因此显然无法按照原始集合进行任何操作。

答案 1 :(得分:2)

马克彼得斯回答的一小部分内容。

使用RegularImmutableSet通过将元素存储两次(一次排序,一次哈希)来保存顺序。这仍然比委托给HashSet的原始HashMap便宜,SingletonImmutableSet为存储的每个元素创建一个条目。

有优化的实施EmptyImmutableSetO(1)。还有许多其他的东西,当你从一个不可变的集合或地图开始时使用。

如果您想了解更多信息,请使用source(但仅取决于文档)。

您链接的性能讨论仅处理哈希冲突。通常,性能为RegularImmutableSet,只是在哈希函数非常糟糕的情况下,它会退化。这适用于所有散列数据结构,但效果不同。 HashSet具有更好的数据位置,{{1}}使用链接,可以更好地处理冲突。

曾经有一个problem,其中某种冲突会导致过多的冲突,但很久以前就已经修复了。现在,偶然遇到类似事情是不可能的。