3

用例:
通过返回ImmutableTable类型的方法处理字符串列表{R,C,V}。例如ImmutableTable of {Integer,String,Boolean} process(String item){...}

收集结果,即合并所有结果并返回ImmutableTable。有没有办法实现它?

当前实施(如 Bohemian 建议的那样):

使用并行流怎么样?下面的代码中是否存在任何并发问题?使用并行流,我在 tableBuilder.build() 上得到“索引 1800 处的 NullPointerException”,但与流一起工作正常。

ImmutableTable<Integer, String, Boolean> buildData() {   

  // list of 4 AwsS3KeyName   
listToProcess.parallelStream() 

  //Create new instance via Guice dependency injection 
.map(s3KeyName -> ProcessorInstanceProvider.get()    
.fetchAndBuild(s3KeyName)) 
.forEach(tableBuilder::putAll); 

 return tableBuilder.build(); }

虽然下面的代码适用于流以及并行流。但是由于行和列的重复条目,ImmutableBuild 失败了。合并表时防止重复的最佳方法是什么?

public static <R, C, V> Collector<ImmutableTable<R, C, V>,     
ImmutableTable.Builder<R, C, V>, ImmutableTable<R, C, V>>   
toImmutableTable() 
{ 
return Collector.of(ImmutableTable.Builder::new, 
ImmutableTable.Builder::putAll, (builder1, builder2) -> 
builder1.putAll(builder2.build()), ImmutableTable.Builder::build); }

编辑:如果在合并不同的表时 ImmutableTable.Builder 中有任何重复的条目,那么它会失败,

试图通过将 ImmutableTables 放入 HashBasedTable 来避免错误

  ImmutableTable.copyOf(itemListToProcess.parallelStream()
            .map(itemString ->
           ProcessorInstanceProvider.get()
                    .buildImmutableTable(itemString))
                    .collect(
                            Collector.of(
                                    HashBasedTable::create,
                                    HashBasedTable::putAll,
                                    (a, b) -> {
                                        a.putAll(b);
                                        return a;
                                    }));
  )

但我收到运行时异常“由:java.lang.IllegalAccessError:试图访问类 com.google.common.collect.AbstractTable 引起”。

我们如何使用 HashBasedTable 作为累加器来收集 ImmutablesTables,因为 HashBasedTable 用最新的条目覆盖现有条目,并且如果我们尝试放置重复条目并返回聚合的不可变表,则不会失败。

4

3 回答 3

7

从 Guava 21 开始,您可以使用ImmutableTable.toImmutableTable收集器。

public ImmutableTable<Integer, String, Boolean> processList(List<String> strings) {
    return strings.stream()
            .map(this::processText)
            .flatMap(table -> table.cellSet().stream())
            .collect(ImmutableTable.toImmutableTable(
                    Table.Cell::getRowKey,
                    Table.Cell::getColumnKey,
                    Table.Cell::getValue,
                    (b1, b2) -> b1 && b2 // You can ommit merge function!
            ));
}

private ImmutableTable<Integer, String, Boolean> processText(String text) {
    return ImmutableTable.of(); // Whatever
}
于 2017-11-15T18:14:46.133 回答
3

这应该有效:

List<String> list; // given a list of String

ImmutableTable result = list.parallelStream()
    .map(processor::process) // converts String to ImmutableTable
    .collect(ImmutableTable.Builder::new, ImmutableTable.Builder::putAll,
        (a, b) -> a.putAll(b.build())
    .build();

这种减少是线程安全的。


HashBasedTable用作中间数据结构:

ImmutableTable result = ImmutableTable.copyOf(list.parallelStream()
    .map(processor::process) // converts String to ImmutableTable
    .collect(HashBasedTable::create, HashBasedTable::putAll, HashBasedTable::putAll));
于 2016-08-17T03:22:42.273 回答
3

Collector您应该能够通过使用Collector.of静态工厂方法创建适当的 来做到这一点:

ImmutableTable<R, C, V> table =
    list.stream()
        .map(processor::process)
        .collect(
            Collector.of(
                () -> new ImmutableTable.Builder<R, C, V>(),
                (builder, table1) -> builder.putAll(table1),
                (builder1, builder2) ->
                    new ImmutableTable.Builder<R, C, V>()
                        .putAll(builder1.build())
                        .putAll(builder2.build()),
                ImmutableTable.Builder::build));
于 2016-08-17T08:48:29.033 回答