我有两组对象(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
只是一个包含两个对象的类。)
答案 0 :(得分:2)
这里有两件事。第一个是如何将二维迭代线性化为流,第二个是如何将结果存储到某个数据结构中。
将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
。