我正在寻找一种简洁的方法,将导致不同操作的if
和else
语句转换为lambdas和stream。 / p>
假设我有这段代码:
List<OuterData> result = new LinkedList<>();
for (Outer outer : getOutersFromSomewhere()) {
OuterData outerData = new OuterData();
if (outer.isImportant()) {
doImportantAction(outer, outerData);
} else if (outer.isTrivial()) {
doTrivialAction(outer, outerData);
} else {
doDefaultAction(outer, outerData);
}
for (Inner inner : outer.getInners()) {
if (inner.mustBeIncluded()) {
InnerData innerData = new InnerData();
if (inner.meetsCondition1()) {
doAction1(inner, innerData, outer, outerData);
} else if (inner.meetsCondition2()) {
doAction2(inner, innerData, outer, outerData);
} else {
doDefaultAction(inner, innerData, outer, outerData);
}
outerData.add(innerData);
}
}
result.add(outerData);
}
return result;
这比我的实际代码简化了。我知道它可以被优化和重构,即我可以将内部for
移动到private
方法。我想知道如何将if
,else if
和else
部分翻译成溪流和lambdas。
我知道如何翻译这个例子的骨架。我使用List.stream()
,Stream.map()
,Stream.filter()
,Stream.collect()
和Stream.peek()
。我的问题只是条件分支。我该怎么做这个翻译?
答案 0 :(得分:5)
第一个显而易见的方法是流式传输元素,根据所需条件过滤元素,然后对每个剩余元素应用操作。这也使代码更清晰:
List<Outer> outers = getOutersFromSomewhere();
outers.stream().filter(Outer::isImportant)
.forEach(outer -> doImportantAction(outer, outerDate));
outers.stream().filter(Outer::isTrivial)
.forEach(outer -> doTrivialAction(outer, outerDate));
// default action analog
警告:仅当重要元素,普通元素和默认元素构成分区时才有效。否则它不等同于你的if-else结构。但也许这是打算......
这种方法的主要问题是:OOP不是很好。您正在查询对象以便做出决定。但是OOP应该是&#34;告诉,不要问&#34;尽可能多。
另一个解决方案是在Outer
类中提供一种消费方法:
public class Outer {
...
public void act(OuterData data, Consumer<Outer> importantAction,
Consumer<Outer> trivialAction, Consumer<Outer> defaultAction) {
if (isImportant())
importantAction.accept(this, data);
else if (isTrivial())
trivialAction.accept(this, data);
else
defaultAction.accept(this, data);
}
}
现在你称它为这么简单:
List<Outer> outers = getOutersFromSomewhere();
outers.forEach(outer -> outer.act(...)); // place consumers here (lambdas)
这有一个明显的优势:如果您必须为Outer
课程添加功能 - 让我们说isComplex()
- 您只需更改该单个班级的内部(并且可能解决其他部分的编译器故障)。或者,您可以以向后兼容的方式添加此功能。
相同的规则可以应用于Inner
类和迭代。