将循环内的复杂条件逻辑转换为流和 lambda
Translate complex conditional logic inside a loop into streams and lambdas
我正在寻找一种干净的方法来将具有 if
和 else
语句的复杂逻辑条件 导致不同的操作 ,转换为 lambda 和流。
假设我有这个代码:
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
部分转换为流和 lambda。
我知道如何翻译这个例子的骨架。我会使用 List.stream()
、Stream.map()
、Stream.filter()
、Stream.collect()
和 Stream.peek()
。我的问题仅在于条件分支。我该如何翻译?
第一个明显的方法是流式传输您的元素,根据需要的标准过滤它们,然后对每个剩余元素应用操作。这也使代码更清晰:
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应该尽可能"tell, don't ask"。
所以另一种解决方案是在您的 Outer
class:
中提供一个消费方法
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
class 添加一个功能 - 比方说 isComplex()
- 您只需更改该单一的内部结构class(并可能解决其他部分的编译器故障)。或者您可以以向后兼容的方式添加此功能。
相同的规则可以应用于 Inner
class 和迭代。
我正在寻找一种干净的方法来将具有 if
和 else
语句的复杂逻辑条件 导致不同的操作 ,转换为 lambda 和流。
假设我有这个代码:
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
部分转换为流和 lambda。
我知道如何翻译这个例子的骨架。我会使用 List.stream()
、Stream.map()
、Stream.filter()
、Stream.collect()
和 Stream.peek()
。我的问题仅在于条件分支。我该如何翻译?
第一个明显的方法是流式传输您的元素,根据需要的标准过滤它们,然后对每个剩余元素应用操作。这也使代码更清晰:
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应该尽可能"tell, don't ask"。
所以另一种解决方案是在您的 Outer
class:
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
class 添加一个功能 - 比方说 isComplex()
- 您只需更改该单一的内部结构class(并可能解决其他部分的编译器故障)。或者您可以以向后兼容的方式添加此功能。
相同的规则可以应用于 Inner
class 和迭代。