2016-08-16 7 views
1

Use case:
Список процессов с помощью метода, который возвращает ImmutableTable типа {R,C,V}. Например, ImmutableTable of {Integer,String,Boolean} process(String item){...}Java 8 collector для Guava неизменяемый стол

Соберите результат i.e, объедините все результаты и верните ImmutableTable. Есть ли способ достичь этого?

Текущая реализация (как это было предложено артистический):

Как насчет использования параллельного потока? Существуют ли проблемы параллелизма в приведенном ниже коде? С параллельным потоком я получаю «NullPointerException в индексе 1800» на tableBuilder.build(), но отлично работает с потоком.

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

Edit: Если есть дубликат записи в ImmutableTable.Builder при объединении различных таблиц, то это не удается,

Пытаясь избежать faluire, поставив 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 переопределяет существующую запись последним и не терпит неудачу, если мы попытаемся поместить повторяющуюся запись и вернуть агрегированную неизменяемую таблицу.

+3

Можете ли вы показать код, который не может быть прав? –

+1

FYI: [Guava 21 будет поддерживать Java 8 и будет иметь коллекционеры для своих коллекций] (https://groups.google.com/forum/#!topic/guava-discuss/ZRmDJnAq9T0). – Xaerxess

ответ

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

Как использовать параллельный поток? Вы видите здесь проблемы параллелизма? общественного ImmutableTable выборки() { listToProcess.parallelStream() // список 4 AwsS3KeyName .map (s3KeyName -> ProcessorInstanceProvider.get() // Создать новый экземпляр с помощью инъекции зависимостей Guice.build (s3KeyName)) .forEach (tableBuilder :: putAll); return tableBuilder.build(); } – sidss

+1

В документе не говорится, что 'ImmutableTable' является потокобезопасным, но см. Измененный код, который является потоковым (а также теперь только одна строка :)) – Bohemian

+0

Большое спасибо за предоставление этого решения. Builld терпит неудачу из-за дубликатов, любезно скажите, что может быть лучшим способом предотвратить дубликаты? Кажется, мне придется использовать HashBasedTable. – sidss

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

Я думаю, вы могли бы использовать ссылки на методы для Поставщика (ImmutableTable.Builder :: new) и BiConsumer (ImmutableTable.Builder :: putAll). – srborlongan

+1

Я не уверен, что вы можете: я попробовал «ImmutableTable.Builder :: new», и он не мог вывести типы. –

+1

Объединитель можно оптимизировать, повторно используя один из строителей. Например: builder1.putAll (builder2.build()) ' – mfulton26

1

С 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 
} 
+0

Это должен быть принятый ответ. – RedShift

 Смежные вопросы

  • Нет связанных вопросов^_^