Hashset vs Treeset

2022-08-31 04:23:14

我一直很喜欢树,那漂亮,它们很整洁。但是,我认识的每个软件工程师都尖锐地问我为什么我会使用.从CS背景来看,我认为使用哪个并不重要,我也不在乎弄乱哈希函数和桶(在的情况下)。O(n*log(n))TreeSetJava

在哪些情况下我应该使用 a over a ?HashSetTreeSet


答案 1

HashSet比TreeSet快得多(对于大多数操作(如添加,删除和包含等大多数操作的常量时间与日志时间),但没有像TreeSet那样提供排序保证。

哈希集

  • 该类为基本操作(添加、删除、包含和大小)提供恒定的时间性能。
  • 它不能保证元素的顺序会随着时间的推移而保持不变
  • 迭代性能取决于哈希集的初始容量负载因子
    • 接受默认负载因子非常安全,但您可能希望指定一个初始容量,该容量大约是您预期集增长到的两倍的大小。

树集

  • 保证基本操作(添加,删除和包含)的日志(n)时间成本
  • 保证 set 的元素将被排序(升序、自然或您通过其构造函数指定的元素)(实现 SortedSet)
  • 不提供任何迭代性能的调整参数
  • 提供了一些方便的方法来处理有序集,如first()headSet()tailSet()last()

要点:

  • 两者都保证了元素的无重复收集
  • 通常,将元素添加到 HashSet,然后将集合转换为树集以进行无重复排序遍历通常更快。
  • 这些实现都不会同步。也就是说,如果多个线程同时访问一个集,并且至少有一个线程修改了该集,则必须在外部同步该集。
  • LinkedHashSet 在某种意义上介于 和 之间。作为一个哈希表实现,其中有一个链接列表贯穿其中,但是,它提供了插入顺序迭代,这与TreeSet保证的排序遍历不同HashSetTreeSet

因此,用法的选择完全取决于您的需求,但我觉得即使您需要一个有序的集合,那么您仍然应该更喜欢HashSet来创建集合,然后将其转换为TreeSet。

  • 例如:SortedSet<String> s = new TreeSet<String>(hashSet);

答案 2

a尚未提及的一个优点是它具有更大的“局部性”,这是说(1)如果两个条目在顺序中附近,则将它们放在数据结构中彼此靠近的简写,因此在内存中;(2)这种放置利用了局部性原则,该原则表明相似的数据通常由具有相似频率的应用程序访问。TreeSetTreeSet

这与 相反,a 将条目分散到整个内存中,无论它们的键是什么。HashSet

当从硬盘驱动器读取数据的延迟成本是从缓存或RAM读取成本的数千倍时,并且当数据确实以局部性访问时,这可能是一个更好的选择。TreeSet


推荐