【问题标题】:Guava's ImmutableTable filtering via Java 8 parallel stream通过 Java 8 并行流过滤 Guava 的 ImmutableTable
【发布时间】:2016-09-01 07:30:39
【问题描述】:

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

过滤表不可变;

用例:遍历 toFilter 并删除 validEntry 表中不存在或条目值为 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 做到这一点?

【问题讨论】:

  • 解决您的问题...您的示例看起来甚至没有经过编译(Immutable 不是 Guava 类型,ImmutableTable 是;ImmutableTable 不占用字段 名称但对象类型)。我们不使用伪代码,而是使用真实代码。因此,请创建一个 MCVE 并填写您所拥有的内容,并准确告诉我们您的期望,以便我们为您提供帮助。
  • 已修复。我正在寻找一些指针。

标签: java java-8 guava java-stream collect


【解决方案1】:

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

我知道您写过您的应用程序适用于 Java 8,但使用 Java 8 流和类似的酷东西根本不可能这样做,因为到目前为止,Table 并不是为 Java 8 设计的(无法从 Cells 的 Itera{ble,tor} 构建表;表不需要 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 的魔法,这将使您的代码更具可读性:

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

【讨论】:

  • hmmm... 看起来我忘记了两者之间的buildObjectB。好吧,在每个解决方案中这样做都相当容易。我把它留给你,因为我被你的命名分心了(你的方法叫做filterXxx,但它也可以转换......)另外,对于那个buildObjectB,你总是可以使用Tables.transformValues进行转换。
猜你喜欢
  • 1970-01-01
  • 2015-05-14
  • 2016-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多