java - 我如何比较两个 MultiMaps?

标签 java csv arraylist guava multimap

我有两个从两个巨大的 CSV 文件创建的多图。

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

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

方法一:

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

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

bigList 中将是单独的小列表 A、B、C 等。

我计划在检查第二个 Multimap 中的单个列表包含该“关键”元素的基础上,从两个文件的每个 bigList 中挑选单个列表。如果是,则比较这两个列表并找出无法匹配的任何内容。

方法二:

比较两个 Multimap,但我不确定如何完成。

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

最佳答案

使用Multimaps.filterEntries(Multimap, Predicate) .

如果你想得到两个Multimap之间的差异,很容易写一个基于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);
}

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

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

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


在 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());
  }
}

像这样将它用作 Multimaps.filterEntries() 的参数:

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

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

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

关于java - 我如何比较两个 MultiMaps?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32254598/

相关文章:

java - 发送 freemarker 模板电子邮件

python - 使用 BioPython 搜索 PubMed 并写入 CSV

java - 如何将数组添加到ArrayList (Java)

java - 使用 java Collections 获得意想不到的结果

java - 使用 Java 找出独特的因素

java - 如何通过多个线程成功访问和循环ArrayList?

java - spring security 已经给了token 是不是还要写一个代码把token 存到redis 中?

java - 如何使用并发执行器 future 在java中的固定时间后使方法超时?

mysql - MYSQL中使用IF/CASE语句查找字符串中是否存在子字符串

mysql - 在 phpMyAdmin 中导入带有多边形数据的 CSV