并行创建匹配表

时间:2014-05-30 13:31:32

标签: java parallel-processing guava java-8

我有两组对象(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只是一个包含两个对象的类。)

1 个答案:

答案 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