【问题标题】:Most fastest and efficient way to remove duplicates in Java在 Java 中删除重复项最快和最有效的方法
【发布时间】:2017-10-18 06:23:00
【问题描述】:

我想删除数据中的重复值。我知道这是 stackoverflow 中经常观察到的问题,但我的问题有点不同,因为现在我正在处理非常大的数据。因此,我必须在我的代码中考虑最多的执行时间。

如下sn-p,我做了一个简单的删除重复值的代码。

// Suppose that the dataset is very huge so that
// multi-node resources should be necessary.    
String[] data = new String[10_000_000];

HashMap<String, String> uniqueItems = new HashMap<>();

for (int i = 0; i < data.length; i++) {
    if (uniqueItems.containsKey(data[i])) {
        uniqueItems.remove(data[i]);
        uniqueItems.put(data[i], "inserted");
    } else {
        uniqueItems.put(data[i], "inserted");
    }
}

但是,我不喜欢它,因为我认为其他更好的数据结构或不同的算法可以比我的代码有效地删除重复。

所以我想寻找更好的方法来在数据很大时快速删除重复值。
如果您能告诉我删除重复值的最快方法,我将不胜感激。

另外,我想知道重复值的数量是否会影响性能。我的意思是如果重复值是原始数据的 50%,那么最佳算法和数据结构的选择会改变吗?如果是这样,我想找到一种可以在一般情况下取得良好性能的方法。

【问题讨论】:

标签: java optimization hashmap time-complexity hashset


【解决方案1】:

将您的 uniqueItems 转换为 HashSet&lt;String&gt; 并将您的 for 循环 简单地转换为:

uniqueItems.add(data[i]);

如果add 返回true,那么你插入了一个唯一的字符串; false 如果重复。

在最佳情况下,两种算法都应该在 O(n) 时间内运行,但是当您不关心值(对于给定键)时使用 HashMap 是愚蠢和浪费的资源。 HashSet 更适合这种情况。

您也可以尝试TreeSet&lt;String&gt;,看看哪种方法最适合您的特定数据集。考虑到 JDK 8 新的HashSet 实现,可能会更糟:过度拥挤的存储桶会自动存储为迷你树集,即使 散列函数 表现不佳,也能提供有竞争力的性能。 (此优化仅适用于Comparable 类型,例如String。)


暴力搜索数组。在一个简单的基于数组的算法中,在插入每个元素之前搜索整个数组,你会得到一个非常糟糕的O(n²)性能。

因此,您可能想先排序您的数据,将重复的元素靠近放置。这为您带来了更快的 O(n log n) 性能,但在一般情况下仍落后于 HashMap/HashSet 版本。


理论上最好是线性的。如果不至少访问每个元素一次,您将无法检测到所有 个重复项。因此,我们当前的 O(n) 时间复杂度确实是您可以在这里做到的最好的。

当然,您总是可以尝试减少Big O notation 中的一些隐藏常量,但您不会得到一个渐近更好的算法。

【讨论】:

  • hashSet 比 HashMap 好吗?没看懂
  • @sclee1 两者共享相同的哈希表算法。但是,如果你真的不关心存储的值(对于每个键),那么使用 Hashmap 是愚蠢的;你最好使用 Set 来代替。
  • 感谢您的评论。如果满足某些条件,为什么您的解决方案会给我 O(n) ?(因为您说我需要运气)
  • @sclee1 这取决于您的数据如何存储在超快速哈希图中。请参阅this answer 了解更多注意事项。
  • 为什么你认为使用 HashMap 有 O(n²)?
【解决方案2】:

在您的示例中,数据 [i] 值用作“键” HashMap uniqueItems。

HaspMap 将始终具有唯一键。现有密钥 将被 put() 操作覆盖。如果你不需要 conatinsKey() 你想添加一个新元素。

为什么要删除并插入现有密钥?

【讨论】:

  • 感谢您的评论。这是我的错误:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
  • 2018-05-07
  • 2015-08-02
  • 2010-12-13
  • 2018-04-02
  • 2014-02-22
相关资源
最近更新 更多