我如何比较两个 MultiMaps?
How can I compare two MultiMaps?
我有两个从两个巨大的 CSV 文件创建的多图。
Multimap<String, SomeClassObject> mapOne = ArrayListMultimap.create();
Multimap<String, SomeClassObject> mapTwo = ArrayListMultimap.create();
我假设一个 CSV 列作为一个键,每个键都有数千个与之关联的值。这些 Multimap
中包含的数据应该相同。现在我想比较这些 Multimap
中的数据,看看是否有不同的值。这是我正在考虑的两种方法:
方法一:
从 Multimap
中列出一份大清单。这个大列表将包含一些单独的列表。每个较小的列表都包含一个唯一值,即从 Multimap
读取的 "key" 及其关联值,这些值将构成该单独列表的其余部分。
ArrayList<Collection<SomeClassObject>> bigList = new ArrayList<Collection<SomeClassObject>>();
在bigList
内将是单独的小列表A、B、C等
我计划在检查第二个 Multimap
中的单个列表包含 "key" 元素的基础上,从两个文件的每个 bigList
中选择单个列表。如果是,则比较这两个列表并找到无法匹配的任何内容。
方法二:
比较两个 Multimap
,但我不确定如何完成。
哪种方法的执行时间应该更短?我需要在最短时间内完成手术。
来自 ArrayListMultimap.equals
文档:
Compares the specified object to this multimap for equality.
Two ListMultimap instances are equal if, for each key, they contain the same values in the same order. If the value orderings disagree, the multimaps will not be considered equal.
所以就这样做 mapOne.equals(mapTwo)
。尝试自己做不会有更好的执行时间。
使用Multimaps.filterEntries(Multimap, Predicate)
.
如果你想得到两个Multimap
之间的差异,很容易写一个基于containsEntry
的过滤器,然后使用过滤行为来高效地找到所有不存在的元素'匹配。只需基于一张地图构建 Predicate
,然后过滤另一张地图。
这就是我的意思。在这里,我使用的是 Java 8 lambda,但您可以查看此 post 的修订历史以查看 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 版本相同(结果相同)。
我有两个从两个巨大的 CSV 文件创建的多图。
Multimap<String, SomeClassObject> mapOne = ArrayListMultimap.create();
Multimap<String, SomeClassObject> mapTwo = ArrayListMultimap.create();
我假设一个 CSV 列作为一个键,每个键都有数千个与之关联的值。这些 Multimap
中包含的数据应该相同。现在我想比较这些 Multimap
中的数据,看看是否有不同的值。这是我正在考虑的两种方法:
方法一:
从 Multimap
中列出一份大清单。这个大列表将包含一些单独的列表。每个较小的列表都包含一个唯一值,即从 Multimap
读取的 "key" 及其关联值,这些值将构成该单独列表的其余部分。
ArrayList<Collection<SomeClassObject>> bigList = new ArrayList<Collection<SomeClassObject>>();
在bigList
内将是单独的小列表A、B、C等
我计划在检查第二个 Multimap
中的单个列表包含 "key" 元素的基础上,从两个文件的每个 bigList
中选择单个列表。如果是,则比较这两个列表并找到无法匹配的任何内容。
方法二:
比较两个 Multimap
,但我不确定如何完成。
哪种方法的执行时间应该更短?我需要在最短时间内完成手术。
来自 ArrayListMultimap.equals
文档:
Compares the specified object to this multimap for equality.
Two ListMultimap instances are equal if, for each key, they contain the same values in the same order. If the value orderings disagree, the multimaps will not be considered equal.
所以就这样做 mapOne.equals(mapTwo)
。尝试自己做不会有更好的执行时间。
使用Multimaps.filterEntries(Multimap, Predicate)
.
如果你想得到两个Multimap
之间的差异,很容易写一个基于containsEntry
的过滤器,然后使用过滤行为来高效地找到所有不存在的元素'匹配。只需基于一张地图构建 Predicate
,然后过滤另一张地图。
这就是我的意思。在这里,我使用的是 Java 8 lambda,但您可以查看此 post 的修订历史以查看 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 版本相同(结果相同)。