簡體   English   中英

Guava不可變表的Java 8收集器

[英]Java 8 collector for Guava Immutable Table

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

收集結果,即合並所有結果並返回ImmutableTable 有沒有辦法實現它?

目前的實施(波希米亞建議):

如何使用並行流? 以下代碼中是否存在並發問題? 使用Parallel流我在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(); }

雖然下面的代碼與流和並行流有關。 但是由於row和col的重復輸入,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中來避免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;
                                    }));
  )

但我得到運行時異常“引起:java.lang.IllegalAccessError:嘗試訪問類com.google.common.collect.AbstractTable”。

我們如何使用HashBasedTable作為Accumulator來收集ImmutablesTables,因為HashBasedTable用最新的條目覆蓋現有條目,如果我們嘗試放入重復條目並返回聚合的Immutable表,則不會失敗。

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

這應該工作:

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

您應該可以通過使用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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM