根据 JavaDoc API,HashSet 只是 HashMap 的包装器。因此,在 HashMap 上使用 HashSet 是否有任何性能优势。曾经?曾经?或者只是有一个适合其他情况的不同 API?
2 回答
不,没有“性能”优势;使用正确的 API 来解决正确的问题只会带来好处……这是相当可观的。
并非真的没有性能优势,它们都用于不同的目的。
关于 API 文档中的 Hashset
该类实现了由哈希表(实际上是 HashMap 实例)支持的 Set 接口。它不保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。此类允许空元素。
此类为基本操作(添加、删除、包含和大小)提供恒定的时间性能,假设哈希函数将元素正确地分散在桶中。迭代这个集合需要的时间与 HashSet 实例的大小(元素的数量)加上支持 HashMap 实例的“容量”(桶的数量)的总和成正比。因此,如果迭代性能很重要,那么不要将初始容量设置得太高(或负载因子太低),这一点非常重要。
请注意,此实现不同步。如果多个线程同时访问一个哈希集,并且至少有一个线程修改了该集,则必须在外部进行同步。这通常是通过在一些自然封装集合的对象上同步来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问:
Set s = Collections.synchronizedSet(new HashSet(...));
此类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间修改集合,除了通过迭代器自己的 remove 方法之外,迭代器会抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。
请注意,不能保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。
检查此参考:HashSet