如何比较两个MultiMap?

use*_*240 6 java csv arraylist multimap guava

我有两个由两个巨大的CSV文件创建的Multimap。

Multimap<String, SomeClassObject> mapOne = ArrayListMultimap.create();
Multimap<String, SomeClassObject> mapTwo = ArrayListMultimap.create();
Run Code Online (Sandbox Code Playgroud)

我假设一个CSV列作为键,并且每个键都有成千上万个与之关联的值。这些中包含的数据Multimap应该相同。现在,我想比较这些中Multimap的数据并查找是否有任何不同的值。这是我正在考虑的两种方法:

方法一:

从清单中列出一个大清单Multimap。这个大列表将包含一些单独的列表。每个较小的列表都包含一个唯一值,该值是从中读取的“键” Multimap及其关联的值,它将构成该单个列表的其余部分。

ArrayList<Collection<SomeClassObject>> bigList = new ArrayList<Collection<SomeClassObject>>();
Run Code Online (Sandbox Code Playgroud)

其中bigList将包含单个小列表A,B,C等。

我计划在bigList检查第二个单个列表中是否Multimap包含“ key”元素的基础上,从两个文件中的每个列表中选择单个列表。如果是这样,则将这两个列表进行比较,找到所有无法匹配的内容。

方法二:

比较两个Multimaps,但是我不确定该怎么做。

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

dur*_*597 6

使用Multimaps.filterEntries(Multimap, Predicate)

如果要获取两个Multimaps 之间的差异,可以很容易地编写一个基于的过滤器containsEntry,然后使用过滤行为来有效地查找所有不匹配的元素。只需Predicate基于一个地图构建,然后过滤另一个。

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

{foo=[baz]}
{baz=[baz]}
Run Code Online (Sandbox Code Playgroud)

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


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

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());
  }
}
Run Code Online (Sandbox Code Playgroud)

使用它作为参数,Multimaps.filterEntries()像这样:

Multimap<String, String> firstSecondDifference =
    Multimaps.filterEntries(first, new FilterPredicate(second));

Multimap<String, String> secondFirstDifference =
    Multimaps.filterEntries(second, new FilterPredicate(first));
Run Code Online (Sandbox Code Playgroud)

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

  • @ user3044240也许将来的用户会找到这个答案,并且需要Java 7版本,我将保持原样。 (2认同)