【发布时间】:2026-02-08 03:10:01
【问题描述】:
哪种方式将元素添加到集合中最快?
在我看来,您可以通过 2 种不同的方式做到这一点:
检查要添加的元素是否已经在集合中,如果不在集合中,则添加它。
只需添加它,因为集合具有独特的元素。我不确定这种方式会不会抛出错误。
【问题讨论】:
-
为什么不试试看呢?
哪种方式将元素添加到集合中最快?
在我看来,您可以通过 2 种不同的方式做到这一点:
检查要添加的元素是否已经在集合中,如果不在集合中,则添加它。
只需添加它,因为集合具有独特的元素。我不确定这种方式会不会抛出错误。
【问题讨论】:
直接添加即可。它有检查机制。
来自 add 方法的文档。
如果指定的元素不存在,则将其添加到该集合中。更正式地说,如果此集合不包含元素 e2,则将指定的元素 e 添加到此集合中,使得 (e==null ? e2==null : e.equals(e2))。如果此集合已包含该元素,则调用将保持集合不变并返回 false。
【讨论】:
我做了一些工作来为你检查一下
Random rng = new Random();
ArrayList<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 100000; ++i)
numbers.add(rng.nextInt());
HashSet<Integer> set = new HashSet<>();
long beginNoCheck = System.nanoTime();
for (int i : numbers)
{
set.add(i);
}
long endNoCheck = System.nanoTime();
set = new HashSet<>();
long beginCheck = System.nanoTime();
for (int i : numbers)
{
if (!set.contains(i))
set.add(i);
}
long endCheck = System.nanoTime();
System.out.println("Without check: " + (endNoCheck - beginNoCheck));
System.out.println("With check: " + (endCheck - beginCheck));
看起来,在添加之前检查HashSet 是否包含一个元素要快一些。我得到了类似的结果
不检查:66060748
带支票:46209808不检查:38249163
带支票:32058546不检查:58362677
带支票:34429848不检查:52095512
带支票:39612073不检查:34892990
带支票:28945278不检查:42090287
带支票:38426209
【讨论】:
contains 检查,它完全独立于add 操作。它只能让它运行得更慢。您的测试设计有误,请尝试独立运行这些测试。
您还可以随时检查实现以了解幕后发生的事情:
HashSet 只是一个 HashMap
像下面发布的测试可能会在不同的机器上产生不同的结果,甚至只是在不同的情况下。如果运行时之间没有真正巨大的差异,那么可读性通常比几毫秒要好得多。 通常,整个软件的简单适当的概念和设计远远胜过复杂的技巧。
【讨论】: