我将以下代码转换为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;
}
答案 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));
请注意,这不是流操作,因此您无法并行运行它。无论如何,你无法获得太多的并行性,因为谓词有副作用。