Java 8 个 Guava 不可变收集器 Table
Java 8 collector for Guava Immutable Table
用例:
通过 returns ImmutableTable
类型 {R,C,V}
的方法处理字符串列表。例如ImmutableTable of {Integer,String,Boolean} process(String item){...}
收集结果,即合并所有结果和 return ImmutableTable
。有没有办法实现它?
当前实施(如 Bohemian 所建议):
使用并行流怎么样?下面的代码有并发问题吗?使用并行流,我在 tableBuilder.build() 上获得 "NullPointerException at index 1800",但可以正常使用流。
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 由于行和列的重复条目而失败。合并 table 时防止重复的最佳方法是什么?
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); }
编辑:
如果在合并不同的 table 时 ImmutableTable.Builder 中有任何重复的条目,那么它将失败,
试图通过将 Immutable表放入 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;
}));
)
但我收到运行时异常 "Caused by: java.lang.IllegalAccessError: tried to access class com.google.common.collect.AbstractTable"。
我们如何使用 HashBasedTable 作为累加器来收集 ImmutablesTables,因为 HashBasedTable 会用最新的条目覆盖现有条目,并且如果我们尝试放置重复条目也不会失败,并且 return聚合 Immutable table.
这应该有效:
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));
从 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
}
用例:
通过 returns ImmutableTable
类型 {R,C,V}
的方法处理字符串列表。例如ImmutableTable of {Integer,String,Boolean} process(String item){...}
收集结果,即合并所有结果和 return ImmutableTable
。有没有办法实现它?
当前实施(如 Bohemian 所建议):
使用并行流怎么样?下面的代码有并发问题吗?使用并行流,我在 tableBuilder.build() 上获得 "NullPointerException at index 1800",但可以正常使用流。
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 由于行和列的重复条目而失败。合并 table 时防止重复的最佳方法是什么?
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); }
编辑: 如果在合并不同的 table 时 ImmutableTable.Builder 中有任何重复的条目,那么它将失败,
试图通过将 Immutable表放入 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;
}));
)
但我收到运行时异常 "Caused by: java.lang.IllegalAccessError: tried to access class com.google.common.collect.AbstractTable"。
我们如何使用 HashBasedTable 作为累加器来收集 ImmutablesTables,因为 HashBasedTable 会用最新的条目覆盖现有条目,并且如果我们尝试放置重复条目也不会失败,并且 return聚合 Immutable table.
这应该有效:
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));
从 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
}