Guava 的 ImmutableTable 通过 Java 8 并行流过滤

Guava's ImmutableTable filtering via Java 8 parallel stream

在通过并行流和收集器过滤 Guava 的 ImmutableTable 时需要帮助

Immutable tofilterTable;

Usecase:遍历 toFilter 并删除不存在的元素或 validEntry table 中的条目值为 false 的元素。 通过 for 循环的传统方式:

  ImmutableTable<MarketplaceArc, String, ObjectB> filterInactive(final ImmutableTable<MarketplaceArc, String, ObjectB> toFilter) {

     final ImmutableTable.Builder filteredResultBuilder =
            ImmutableTable.builder();

     final Map<MarketplaceArc, Map<String, ObjectB>> rowMap = 
     browseMappings.rowMap();

     for (final Map.Entry<MarketplaceArc, Map<String, ObjectB>> 
      rowMapEntry : rowMap.entrySet()) {

        for (final Map.Entry<String, ObjectB> entry : 
           rowMapEntry.getValue().entrySet()) {

           if(ifActive(rowMap.getKey, entry)){
            filteredResultBuilder.put(
                    rowMapEntry.getKey(),
                    entry.getKey(),
                    buildObjectB(entry));
               }
        }
    }
    return filteredResultBuilder.build();
}

有没有更好更简洁的方法通过 Java parallelStreams 做到这一点?

是的,你可以做得更好。您可以使用 Table.Cell 作为其中之一。这样,您就可以将两个循环缩减为一个。您甚至可以使用谓词使您的方法更通用。

我知道您写过您的应用程序适用于 Java 8,但是使用 Java 8 流和类似的很酷的东西根本不可能这样做,因为 Table到目前为止,对于 Java 8 的设计还不是很好(无法从 Cells 的 Itera{ble,tor} 构建 table;tables 不不需要 BiPredicateTriPredicate)。因此,让我们改进您的代码,简单明了。

普通旧循环,针对 Tables

进行了优化

这是基本版本。没有什么特别的,但是比你的方式做得更好,因为它不依赖于中间复杂的数据结构(你一直在使用地图,例如,这个解决方案没有)。

ImmutableTable<MarketplaceArc, String, ObjectB> filterInactive(Table<MarketplaceArc, String, ObjectB> unfiltered) {
  ImmutableTable.Builder<MarketplaceArc, String, ObjectB> filtered = ImmutableTable.builder();
  for (Table.Cell<MarketplaceArc, String, ObjectB> cell: unfiltered.cells()) {
    if (isActive(cell.getRow(), cell.getValue())) {
      filtered.put(cell);
    }
  }
  return filtered.build();
}

带谓词的通用解决方案

更通用的解决方案是使用通用过滤方法。这将使您的代码更具可读性,感谢一些 Java 8 magic:

// Generic method.
<R,C,V> ImmutableTable<R,C,V> filterToImmutable(Table<R,C,V> unfiltered, Predicate<Table.Cell<R,C,V>> predicate) {
  ImmutableTable.Builder<R,C,V> filtered = ImmutableTable.builder();

  // Actually, let's use some Java 8, just because we can!
  unfiltered.cells().parallelStream()
      .filter(predicate)
      .foreach(filtered::put);
  return filtered.build();
}

// Specific predicate
boolean isActiveCell(Table.Cell<MarketplaceArc, String, ObjectB> cell) {
  return isActive(cell.getRow(), cell.getValue());
}

// Use all you've written, with some Java 8, just because we can. Again.
ImmutableTable<MarketplaceArc, Map<String, ObjectB> unfiltered = ... ;
ImmutableTable<MarketplaceArc, Map<String, ObjectB> filtered = filterToImmutable(unfiltered, this::isActiveCell);