Guava不可变表的Java 8收集器

使用案例:
通过返回类型为{R,C,V} ImmutableTable的方法的进程列表。 例如ImmutableTable of {Integer,String,Boolean} process(String item){...}

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

目前的实施(波希米亚建议):

如何使用并行流? 以下代码中是否存在并发问题? 使用Parallel流我在tableBuilder.build()上得到“索引1800处的NullPointerException”,但是对于流工作正常。

 ImmutableTable 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(); } 

虽然下面的代码非常适合流和并行流。 但是由于row和col的重复输入,ImmutableBuild失败了。 什么是在合并表时防止重复的最佳方法?

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

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

试图通过将ImmutableTables放在HashBasedTable中来避免faluire

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

但我得到运行时exception“引起:java.lang.IllegalAccessError:尝试访问类com.google.common.collect.AbstractTable”。

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

这应该工作:

 List 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)); 

您应该可以通过使用Collector.of静态工厂方法创建适当的Collector来完成此操作:

 ImmutableTable table = list.stream() .map(processor::process) .collect( Collector.of( () -> new ImmutableTable.Builder(), (builder, table1) -> builder.putAll(table1), (builder1, builder2) -> new ImmutableTable.Builder() .putAll(builder1.build()) .putAll(builder2.build()), ImmutableTable.Builder::build)); 

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

 public ImmutableTable processList(List 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 processText(String text) { return ImmutableTable.of(); // Whatever }