如何比较两个MultiMaps?

时间:2015-08-27 16:13:09

标签: java csv arraylist guava multimap

我有两个Multimaps,它们是从两个巨大的CSV文件创建的。

Multimap<String, SomeClassObject> mapOne = ArrayListMultimap.create();
Multimap<String, SomeClassObject> mapTwo = ArrayListMultimap.create();

我假设有一个CSV列作为密钥,每个密钥都有数千个与之关联的值。这些Multimap中包含的数据应该相同。现在我想比较这些Multimap中的数据,并查找是否有任何值不同。以下是我想到的两种方法:

方法一:

Multimap制作一个大清单。这个大清单将包含一些单独的清单。每个较小的列表都包含一个唯一值,即&#34;键&#34;从Multimap读取及其相关值,这些值将形成该单个列表的其余部分。

ArrayList<Collection<SomeClassObject>> bigList = new ArrayList<Collection<SomeClassObject>>();

bigList内的个人小名单A,B,C等。

我打算在检查来自第二个bigList的个别列表包含&#34;键&#34;的基础上,从两个文件中的每个Multimap中挑选单个列表。元件。如果是,则比较这两个列表并找到任何无法匹配的内容。

方法二:

比较Multimap,但我不确定如何做到这一点。

哪种方法应该有更短的执行时间?我需要在最短的时间内完成操作。

2 个答案:

答案 0 :(得分:4)

使用Multimaps.filterEntries(Multimap, Predicate)

如果你想获得两个Multimap之间的差异,可以很容易地编写基于containsEntry的过滤器,然后使用过滤行为来有效地找到所有不是Predicate的元素。比赛。只需根据一个地图构建public static void main(String[] args) { Multimap<String, String> first = ArrayListMultimap.create(); Multimap<String, String> 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<String, String> firstSecondDifference = Multimaps.filterEntries(first, e -> !second.containsEntry(e.getKey(), e.getValue())); Multimap<String, String> secondFirstDifference = Multimaps.filterEntries(second, e -> !first.containsEntry(e.getKey(), e.getValue())); System.out.println(firstSecondDifference); System.out.println(secondFirstDifference); } ,然后过滤另一个地图。

这就是我的意思。在这里,我使用的是Java 8 lambdas,但您可以查看本文的修订历史以查看Java 7版本:

{foo=[baz]}
{baz=[baz]}

在这个人为的例子中,输出是不在另一个列表中的元素:

public static class FilterPredicate<K, V> implements Predicate<Map.Entry<K, V>> {
  private final Multimap<K, V> filterAgainst;

  public FilterPredicate(Multimap<K, V> filterAgainst) {
    this.filterAgainst = filterAgainst;
  }

  @Override
  public boolean apply(Entry<K, V> arg0) {
    return !filterAgainst.containsEntry(arg0.getKey(), arg0.getValue());
  }
}

如果地图匹配,这些多重映射将为空。

在Java 7中,您可以使用以下内容手动创建谓词:

Multimaps.filterEntries()

使用它作为Multimap<String, String> firstSecondDifference = Multimaps.filterEntries(first, new FilterPredicate(second)); Multimap<String, String> secondFirstDifference = Multimaps.filterEntries(second, new FilterPredicate(first)); 的参数,如下所示:

                .find({
                    filter: {
                        order: "name asc"
                    }
                })

否则,代码与上面的Java 8版本相同(结果相同)。

答案 1 :(得分:2)

来自ArrayListMultimap.equals doc:

  

将指定对象与此multimap进行相等比较。

     

如果对于每个键,它们包含相同顺序的相同值,则两个ListMultimap实例是相等的。如果值排序不一致,则多重映射将不被视为相等。

所以只做mapOne.equals(mapTwo)。通过尝试自己完成,你不会有更好的执行时间。