【问题标题】:What it is the best performance way to grab duplicates from a large Set<String>?从大型 Set<String> 中获取重复项的最佳性能方式是什么?
【发布时间】:2013-04-24 20:01:55
【问题描述】:

我有一个很大的Set&lt;String&gt;,其中包含很多单词,比如:

"aaa, cCc, dDD, AAA, bbB, BBB, AaA, CCc, ..."

我想对 Set 中的所有重复单词进行分组,忽略单词的大小写敏感性,然后将它们保存在 Vector&lt;Vector&lt;String&gt;&gt; 或其他任何内容中,因此每个 Vector&lt;String&gt; 项目将包含一组相似的单词,如下所示:

Vector&lt;String&gt;: aaa, AAA, AaA, ...

Vector&lt;String&gt;抄送,抄送,...

Vector&lt;String&gt;: bbB, BBB, ...

我关心性能,因为这个 Set 包含很多单词。

【问题讨论】:

  • 1/你提前知道目标字符串的完整列表吗?
  • 2/ 你为什么使用 Vector 而不是 ArrayList 或 LinkedList?
  • 当它们首先被“添加”到 Set 时,您能否替换“Set”实现以将值排序到内部结构中。我意识到这不是你问的,但似乎切换你的集合实现可能会使这更容易。
  • “我关心性能,因为这个 Set 包含很多单词。” 您是否足够关心是否已经在其上运行了分析器,或者您只是在猜测?
  • 如果你关心性能,不要使用线程安全的Vector;请改用 ArrayList 或 HashSet。

标签: java set duplicates


【解决方案1】:

如果您真的关心性能,您不会使用Vector。至于排序问题,一种解决方案是使用 TreeMapTreeSet 对象并创建一个 Comparator 来执行您想要的相等(排序)。

实例化可能是:

new TreeMap<String,LinkedList<String>>(new Comparator<String>() {

   // comparator here

});

用法:

LinkedList<String> entry = map.get(nextKey);
if (entry == null) {
  entry = new LinkedList<String>()
  map.put(nextKey, entry);
}
entry.add(nextKey);

【讨论】:

    【解决方案2】:

    我会创建一个HashMap&lt;String, Vector&lt;String&gt;&gt; hashMap。 接下来,对于集合中的每个“字符串”

    if (!hashMap.containsKey(string.toLowerCase()){
         Vector v = new Vector();
         v.add(string);
          hashMap.put(string.toLowerCase(), v);
    } else { 
         hashMap.get(string.toLowerCase()).add(string);
    }
    

    最后,如果需要,创建一个向量向量,或者使用 hashmap.valueSet()

    【讨论】:

    • 非常感谢...我做了一些更改,例如如果 Set 中的某些单词没有重复项,因此无需将它们添加到 HashMap。
    【解决方案3】:

    如果您可以选择Set 实现,您可以使用TreeSetComparator,它比较字符串忽略大小写。然后,您将能够遍历排序列表并轻松对重复项进行分组。

    【讨论】:

      【解决方案4】:

      这对输入集进行了一次迭代,我怀疑你能不能比这快得多。将ArrayLists 换成LinkedLists 可能会用局部性换取更少的复制,这可能会提高性能,但我对此表示怀疑。代码如下:

      Set<String> input = new HashSet<String>(Arrays.asList(
          "aaa", "cCc", "dDD", "AAA", "bbB", "BBB", "AaA", "CCc"));
      
      Map<String, List<String>> tmp = new HashMap<String, List<String>>();
      
      for (String s : input) {
          String low = s.toLowerCase();
          List<String> l = tmp.get(low);
      
          if (l == null) {
              l = new ArrayList<String>();
              tmp.put(low, l);
          }
      
          l.add(s);
      }
      
      final List<List<String>> result = new ArrayList<List<String>>(tmp.values());
      

      【讨论】:

        猜你喜欢
        • 2022-08-16
        • 1970-01-01
        • 2018-03-09
        • 1970-01-01
        • 1970-01-01
        • 2017-04-15
        • 1970-01-01
        • 1970-01-01
        • 2021-01-28
        相关资源
        最近更新 更多