如何比较两个MultiMaps?
我有两个Multimaps,它们是从两个巨大的CSV文件创建的。
Multimap mapOne = ArrayListMultimap.create(); Multimap mapTwo = ArrayListMultimap.create();
我假设一个CSV列作为密钥,每个密钥都有数千个与之关联的值。 这些Multimap
包含的数据应该相同。 现在我想比较这些Multimap
的数据,并查找是否有任何值不同。 以下是我想到的两种方法:
方法一:
从Multimap
一个大列表。 这个大清单将包含一些单独的清单。 每个较小的列表都包含一个唯一值,该值是从Multimap
读取的“关键”及其相关值,它将构成该单个列表的其余部分。
ArrayList<Collection> bigList = new ArrayList<Collection>();
在bigList
中将是单个小列表A,B,C等。
我计划在检查来自第二个Multimap
单个列表包含该“key”元素的基础上从两个文件的每个bigList
中选择单个列表。 如果是,则比较这两个列表并找到任何无法匹配的内容。
方法二:
比较Multimap
但我不确定如何做到这一点。
哪种方法应该有更短的执行时间? 我需要在最短的时间内完成操作。
使用Multimaps.filterEntries(Multimap, Predicate)
。
如果要获得两个Multimap
之间的差异,可以很容易地编写基于containsEntry
的filter,然后使用过滤行为来有效地查找所有不匹配的元素。 只需基于一个地图构建Predicate
,然后过滤另一个。
这就是我的意思。 在这里,我使用的是Java 8 lambdas,但您可以查看本文的修订历史以查看Java 7版本:
public static void main(String[] args) { Multimap first = ArrayListMultimap.create(); Multimap second = ArrayListMultimap.create(); first.put("foo", "foo"); first.put("foo", "bar"); first.put("foo", "baz"); first.put("bar", "foo"); first.put("baz", "bar"); second.put("foo", "foo"); second.put("foo", "bar"); second.put("baz", "baz"); second.put("bar", "foo"); second.put("baz", "bar"); Multimap firstSecondDifference = Multimaps.filterEntries(first, e -> !second.containsEntry(e.getKey(), e.getValue())); Multimap secondFirstDifference = Multimaps.filterEntries(second, e -> !first.containsEntry(e.getKey(), e.getValue())); System.out.println(firstSecondDifference); System.out.println(secondFirstDifference); }
在这个人为的例子中,输出是不在另一个列表中的元素:
{foo=[baz]} {baz=[baz]}
如果地图匹配,这些多重映射将为空。
在Java 7中,您可以使用以下方法手动创建谓词:
public static class FilterPredicate implements Predicate> { private final Multimap filterAgainst; public FilterPredicate(Multimap filterAgainst) { this.filterAgainst = filterAgainst; } @Override public boolean apply(Entry arg0) { return !filterAgainst.containsEntry(arg0.getKey(), arg0.getValue()); } }
将它用作Multimaps.filterEntries()
的参数,如下所示:
Multimap firstSecondDifference = Multimaps.filterEntries(first, new FilterPredicate(second)); Multimap secondFirstDifference = Multimaps.filterEntries(second, new FilterPredicate(first));
否则,代码与上面的Java 8版本相同(具有相同的结果)。
从ArrayListMultimap.equals
doc:
将指定对象与此multimap进行相等性比较。
如果对于每个键,它们包含相同顺序的相同值,则两个ListMultimap实例是相等的。 如果值排序不一致,则多重映射将不被视为相等。
所以只需做mapOne.equals(mapTwo)
。 通过尝试自己完成,您将无法获得更好的执行时间。