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