将循环内的复杂条件逻辑转换为流和lambda

Fed*_*ner 5 lambda loops if-statement java-8 java-stream

我正在寻找一种简洁的方法来将复杂的逻辑条件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;
Run Code Online (Sandbox Code Playgroud)

这比我的实际代码简化了.我知道它可以被优化和重构,即我可以将内部移动forprivate方法.我想知道如何翻译if,else if以及else部分流和lambda表达式.

我知道如何翻译这个例子的骨架.我会使用List.stream(),Stream.map(),Stream.filter(),Stream.collect()Stream.peek().我的问题只是条件分支.我该怎么做这个翻译?

See*_*ose 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
Run Code Online (Sandbox Code Playgroud)

警告:仅当重要元素,普通元素和默认元素构成分区时才有效.否则它不等同于你的if-else结构.但也许这是打算......

这种方法的主要问题是:OOP不是很好.您正在查询对象以便做出决定.但OOP应尽可能"告诉,不要问".

所以另一种解决方案是在你的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你称它为这么简单:

List<Outer> outers = getOutersFromSomewhere();
outers.forEach(outer -> outer.act(...)); // place consumers here (lambdas)
Run Code Online (Sandbox Code Playgroud)

这有一个明显的优势:如果你必须为你的Outer类添加一个功能- 比方说isComplex()- 你只需要改变那个单一类的内部(并且可能解决其他部分的编译失败).或者,您可以以向后兼容的方式添加此功能.

可以将相同的规则应用于Inner类和迭代.