Guava不可变表的Java 8收集器

时间:2016-08-16 22:51:19

标签: java java-8 guava immutable-collections

用例:
处理字符串的方法列表,返回类型ImmutableTable的{​​{1}}。例如{R,C,V}

收集结果,即合并所有结果并返回ImmutableTable of {Integer,String,Boolean} process(String item){...}。有没有办法实现它?

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

如何使用并行流?以下代码中是否存在并发问题?使用并行流我在索引1800和#34;得到" NullPointerException;在tableBuilder.build()上,但与流工作正常。

ImmutableTable

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

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

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

通过将ImmutableTables放入HashBasedTable

来试图避免faluire
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); }

但是我得到了运行时异常&#34;引起:java.lang.IllegalAccessError:试图访问com.google.common.collect.AbstractTable和#34;类。

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

3 个答案:

答案 0 :(得分:5)

自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
}

答案 1 :(得分: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));

答案 2 :(得分:3)

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

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