我有两组对象(X,Y),我想将 X 中的所有元素与 Y 中的所有元素进行比较,并将结果值写入匹配表中。
我的第一个方法是必须有两个 for 循环,它们迭代集合并将结果写入表中。
Table<Object, Object, Double>matchTable = TreeBasedTable.create(new ObjectComparator(), new ObjectComparator());
for (Object x : X) {
for (Object y : Y) {
double diff = comparator.diff(x, y);
matchTable.put(x, y, diff);
}
}
由于 Java 8 有更多并行处理的可能性,我想做同样的事情,但并行。我的第一次尝试看起来像这样,但我认为这不是应该的方式,我认为最好使用一些Collector
来创建表并写入它。
Function<Pair<Object>, Boolean> colF = pair -> {
double diff = comparator.diff(pair.x, pair.y);
matchTable.put(pair.x, pair.y, diff);
return true;
};
Function<Object, Long> rowF = x -> {
return Y.parallelStream().map(y -> {
return colF.apply(new Pair<Object>(x, y));
}).count();
};
long count = X.parallelStream().map(rowF).count();
(我只是调用 count()
,因为否则它会延迟执行。Pair
只是一个包含两个对象的类。)
最佳答案
这里发生了两件事。第一个是如何将二维迭代线性化为流,第二个是如何将结果存储到某种数据结构中。
将 2D 迭代线性化为流的一个有用习惯是使用行值驱动外部流,并调用 flatMap
返回该行的所有列值的流。这通常需要某种结对结构,但你已经接受了。代码看起来像这样:
X.stream()
.flatMap(x -> Y.stream().map(y -> new Pair(x, y)))
.forEach(System.out::println);
这会将所有对生成线性流并将其打印出来。
我不知道Guava的TreeBasedTable
是如何工作的。它看起来不是线程安全的,但这没关系,因为流收集器可以处理非线程安全的情况。但是,收集器需要合并中间结果,但我不知道如何使用 Guava Table
对象来做到这一点。其他人必须提供该信息。
如果您想将值收集到按对键控的映射(而不是表格)中,您可以执行以下操作:
X.stream()
.flatMap(x -> Y.stream().map(y -> new Pair(x, y)))
.collect(toMap(pair -> pair, pair -> pair.a + pair.b));
如果要并行运行流,则应使用 toConcurrentMap
而不是 toMap
。
关于java - 并行创建匹配表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23955837/