【问题标题】:Which is faster? Checking if an element is already in a set, if not add it or just adding it anyway?哪个更快?检查一个元素是否已经在一个集合中,如果没有添加它或者只是添加它?
【发布时间】:2026-02-08 03:10:01
【问题描述】:

哪种方式将元素添加到集合中最快?

在我看来,您可以通过 2 种不同的方式做到这一点:

  • 检查要添加的元素是否已经在集合中,如果不在集合中,则添加它。

  • 只需添加它,因为集合具有独特的元素。我不确定这种方式会不会抛出错误。

【问题讨论】:

  • 为什么不试试看呢?

标签: java set add


【解决方案1】:

直接添加即可。它有检查机制。

来自 add 方法的文档。

如果指定的元素不存在,则将其添加到该集合中。更正式地说,如果此集合不包含元素 e2,则将指定的元素 e 添加到此集合中,使得 (e==null ? e2==null : e.equals(e2))。如果此集合已包含该元素,则调用将保持集合不变并返回 false。

【讨论】:

    【解决方案2】:

    我做了一些工作来为你检查一下

    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 操作。它只能让它运行得更慢。您的测试设计有误,请尝试独立运行这些测试。
    • @Zereges 我认为您的测试受到某种 JVM 预热效应的影响。请参阅有关 Java 中正确的微基准测试设计的帖子:*.com/questions/504103/…
    【解决方案3】:

    您还可以随时检查实现以了解幕后发生的事情:

    HashSet 只是一个 HashMap

    http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.getEntry%28java.lang.Object%29

    像下面发布的测试可能会在不同的机器上产生不同的结果,甚至只是在不同的情况下。如果运行时之间没有真正巨大的差异,那么可读性通常比几毫秒要好得多。 通常,整个软件的简单适当的概念和设计远远胜过复杂的技巧。

    【讨论】:

      最近更新 更多