使用Java 8的更好方法

时间:2016-06-08 20:34:14

标签: java java-8 java-stream

我将以下代码转换为java 8代码。我想知道我是否做得恰到好处还是有其他好办法。

Java 7

for (final Category category : categories) {
      final List<Category> subCategories = getCategories(category);
      if (subCategories != null) {
        currentLevel.addAll(subCategories);
      }
    }

Java8

categories.stream().map(category -> getCategories(category)).filter(list->list!=null).flatMap(cat -> cat.parallelStream()).collect(Collectors.toList())

任何java 8方式将以下代码解析为紧凑形式。

while (CollectionUtils.isNotEmpty(currentLevel)) {
  for (final Iterator<Category> iterator = currentLevel.iterator(); iterator.hasNext();) {
    final Category category = iterator.next();
    if (result == null) {
      result = new HashSet<Category>();
    }
    if (!result.add(category)) {
      // avoid cycles by removing all which are already found
      iterator.remove();
    }
  }

  if (currentLevel.isEmpty()) {
    break;
  }
  final Collection<Category> nextLevel = getAllSubcategories(currentLevel);
  currentLevel = nextLevel;
}

3 个答案:

答案 0 :(得分:5)

你的解决方案没问题,只是平行映射到并行流是没用的。如果您查看OpenJDK / OracleJDK中的flatMap实现,您会发现通过传递给flatMap的lambda创建的流会立即转为顺序模式。因此,您不会有任何并行性,最好将parallelStream()替换为stream()以避免混淆。如果您真的想要并行化工作,那么通常最好只并行化最外层的流。

答案 1 :(得分:4)

可能是偏好问题,但您可以使用方法引用替换这些lambda:

null

太糟糕了,列表显然可能flatMap(真的吗?)...否则你可以使用parallelStream

我不会在另一个流操作中使用{{1}}。

答案 2 :(得分:2)

对于第二个问题,通常基于流的删除重复项的方法是将元素复制到不同的集合中,使用distinct()操作处理它们:

    Collection<Category> currentCopy = currentLevel.stream()
        .distinct()
        .collect(toList());

但似乎你试图在原地操纵集合而不是制作副本。为此,您可以执行以下操作:

    Set<Category> result = new HashSet<>();
    currentLevel.removeIf(cat -> !result.add(cat));

请注意,这不是流操作,因此您无法并行运行它。无论如何,你无法获得太多的并行性,因为谓词有副作用。

相关问题