【问题标题】:Should you check for a duplicate before inserting into a set您是否应该在插入集合之前检查重复项
【发布时间】:2016-01-10 23:50:14
【问题描述】:

我正在学习使用集合。我的问题是:集合不包含重复项。当我们尝试插入重复项时,它不会抛出任何错误并自动删除重复项。在插入集合之前检查每个值是否存在是一种好习惯吗?还是可以执行以下代码之类的操作?我认为 Java 会在内部使用 .contains(value) 进行检查。你怎么看?

考虑到集合中有 n 个元素,这两种情况下的 Big O 复杂度是多少?

import java.util.HashSet;
import java.util.Set;

public class DuplicateTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Set<Integer> mySet = new HashSet<Integer>();

         mySet.add(10);
         mySet.add(20);
         mySet.add(30);
         mySet.add(40);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);

         System.out.println("Contents of the Hash Set :"+mySet);
    }

}

【问题讨论】:

  • 因为HashSet 得到HashMap 的支持,您的答案可以在这里找到:stackoverflow.com/a/4553642/4490686
  • 它不会执行contains,而是不会添加已经存在的元素,即它不会增加任何开销来执行此操作。
  • 仅供参考,您无法通过添加另一个与已应用的操作具有相同复杂性的操作来更改 Big Oh 复杂性。我的意思是,for(int x: set) { set.add(x); }for(int x:set) { set.contains(x); set.add(x); } 具有相同的 Big Oh 复杂度,只要 addcontains 具有相同的复杂度。因为 O(C*n) == O(n),对于任何常数 C。
  • 这取决于你想用你的集合做什么。你想知道如果某事。是重复的,那么这样的检查是必要的,如果你只想删除双连,那么这个集合已经做了你想要的一切。
  • @Aron_dc: 因为add 返回一个boolean 告诉您该元素是否已添加或重复,所以在添加之前从不任何理由进行检查。

标签: java performance set big-o


【解决方案1】:

根据docs

public boolean add(E e)

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

所以add() 方法已经返回一个真或假。所以你不需要做额外的检查。

【讨论】:

    【解决方案2】:

    the API documentation of Set.add(E)比较

    add 方法检查元素是否已经在Set 中。如果元素已经存在,则不添加新元素,Set 保持不变。在大多数情况下,您不需要检查任何内容。

    方法的复杂程度取决于您使用的 Set 的具体实现。

    【讨论】:

      【解决方案3】:

      不检查也没关系。这是与 Sets of Lists 相比的主要优势,因为它们会自动过滤掉重复项。

      HashSet 具有恒定的时间性能 (http://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html)

      这个类为基本操作(添加、删除、包含和大小)提供恒定的时间性能,假设哈希函数将元素正确地分散在桶中

      【讨论】:

      • @YassinHajaj - 已链接到 APIi 并提供了相关部分。
      【解决方案4】:

      add 函数返回一个布尔值,您可以检查该值以确定该项目是否已经在 Set 中。这当然是基于您的需求,并不是最佳实践。很高兴知道它不会删除已经存在的项目,因此如果您根据数据库中的代理键定义 equals,则不能依赖它来使用新信息更新现有值。这与地图的工作方式相反,地图将返回任何现有值并将其替换为新值。

      【讨论】:

        【解决方案5】:

        以下是您问题的答案:

        当我们尝试插入重复项时,它不会抛出任何错误并且 自动删除重复项。

        您的理解不正确。如果新项目已经在集合中,则调用Set.add() 不会添加新项目;此声明适用于Set 的所有实现,包括HashSetTreeSet

        在插入集合之前检查每个值是否是一种好习惯 它是否存在?或者可以做类似下面的事情 代码?我认为java会在内部使用 . 包含(值)。你怎么看?

        因为你的理解从一开始就不正确,所以你不需要在插入集合之前检查每个值是否已经存在。是的,在内部,它正在做类似contains() 的事情。

        考虑到这两种情况,Big Oh 的复杂性是多少 有“n”个元素进入集合?

        对于 HashSet,每个 add() 的时间复杂度为 O(1)。对于TreeSet()——您没有使用它——每个add()的时间复杂度是O(lg N)

        【讨论】:

        • 如果哈希算法不是最优的,HashSet 的复杂度可能为O(n)
        猜你喜欢
        • 2021-01-20
        • 1970-01-01
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2015-10-10
        相关资源
        最近更新 更多