如何检测Map <string,list <string>&gt; </string,list <string>中的重复列表

时间:2013-09-18 16:15:01

标签: java collections

我有Map<String,List<String>>形式的地图。密钥是文档编号,列出符合某些条件且在文档中找到的术语列表。 为了检测重复文档,我想知道List<String>中是否有两个具有完全相同的元素(这包括重复值)。 List<String>已排序,因此我可以遍历地图并首先检查List.size()。对于任何两个列表 我必须将两个列表与List.equals()进行比较。 地图和相关列表永远不会很大,所以即使这种暴力方法不能很好地扩展它 就足够了。但我想知道是否有更好的方法。一种不涉及太多的方式 如果Map和/或Lists变得更大,那么显式循环和不会产生组合爆炸的方法。 最后我需要的是问题的是/否答案:任何列表是否相同?

4 个答案:

答案 0 :(得分:4)

您可以逐个将列表添加到设置数据结构中。令人高兴的是,add方法将告诉您集合中是否已存在相等的列表:

HashSet<List<String>> set = new HashSet<List<String>>();
for (List<String> list : yourMap.values()) {
    if (!set.add(list)) {
        System.out.println("Found a duplicate!");
        break;
    }
}

此算法将查找O(N)时间内是否存在重复列表,其中N是字符串列表中的字符总数。这比比较每对列表要好得多,因为对于n个列表,有n(n-1)/ 2对要比较。

答案 1 :(得分:1)

使用Map.containsValue()。不会比你描述的更有效,但代码会更清晰。链接 - &gt; http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#containsValue%28java.lang.Object%29

此外,根据您为什么要这样做,可能值得研究这个界面 - &gt; http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/BiMap.html

答案 2 :(得分:0)

不确定它是否是更好的方法,但更简洁的方法是创建一个实现Comparable的对象并保存一个List。您可以如上所述实现hashcode()和equals(),并将地图更改为包含此类的实例而不是直接包含Lists。

然后,您可以使用HashSet有效地发现哪些列表相同。或者,您可以将地图的值集合添加到HashSet,并将散列集的大小与Map的大小进行比较。

答案 3 :(得分:0)

来自'List.equals(Object o)'的JavaDoc:

  

将指定对象与此列表进行比较以获得相等性。返回   当且仅当指定的对象也是列表时才为true,两个列表都是如此   具有相同的大小,以及两者中所有相应的元素对   清单是平等的。 (如果(e1 == null,两个元素e1和e2相等)?   e2 == null:e1.equals(e2))。)换句话说,定义了两个列表   如果它们包含相同顺序的相同元素,则相等。这个   定义确保equals方法可以正常工作   List接口的不同实现。

这让我相信它正在做同样的建议:检查以确保双方都是List,然后比较尺寸,然后检查每一对。我不会在那里重新发明轮子。

您可以使用hashCode()代替,但JavaDoc似乎也表明它正在循环:

  

返回此列表的哈希码值。列表的哈希码是   定义为以下计算的结果:

 int hashCode = 1;
  Iterator<E> i = list.iterator();
  while (i.hasNext()) {
      E obj = i.next();
      hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  }

所以,我认为你不会在任何时间保存。但是,您可以编写一个自定义List,在项目放入时计算哈希值。然后,您可以否定执行循环的成本。