yel*_*ver 28 java lambda if-statement java-8
使用Java 8,我有这样的代码:
if(element.exist()){
    // Do something
}
Run Code Online (Sandbox Code Playgroud)
我想转换为lambda风格,
element.ifExist(el -> {
    // Do something
});
Run Code Online (Sandbox Code Playgroud)
使用这样的ifExist方法:
public void ifExist(Consumer<Element> consumer) {
    if (exist()) {
        consumer.accept(this);
    }
}
Run Code Online (Sandbox Code Playgroud)
但现在我还有其他情况要打电话:
element.ifExist(el -> {
    // Do something
}).ifNotExist(el -> {
    // Do something
});
Run Code Online (Sandbox Code Playgroud)
我可以写一个类似的ifNotExist,我希望它们是互斥的(如果exist条件为真,则无需检查ifNotExist,因为有时,exists()方法需要花费很多工作量来检查),但我总是要检查两个倍.我怎么能避免这种情况?
也许"存在"这个词会让别人误解我的想法.你可以想象我还需要一些方法:
 ifVisible()
 ifEmpty()
 ifHasAttribute()
Run Code Online (Sandbox Code Playgroud)
很多人说这是个坏主意,但是:
在Java 8中,我们可以使用lambda forEach而不是传统的for循环.在编程中for,if是两个基本的流程控制.如果我们可以使用lambda作为for循环,为什么使用lambda是个if坏主意?
for (Element element : list) {
    element.doSomething();
}
list.forEach(Element::doSomething);
Run Code Online (Sandbox Code Playgroud)
在Java 8中,有OptionalifPresent,类似于我对ifExist的想法:
Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);
Run Code Online (Sandbox Code Playgroud)
关于代码维护和可读性,如果我有以下代码和许多重复的简单if子句,你怎么看?
    if (e0.exist()) {
        e0.actionA();
    } else {
        e0.actionB();
    }
    if (e1.exist()) {
        e0.actionC();
    }
    if (e2.exist()) {
        e2.actionD();
    }
    if (e3.exist()) {
        e3.actionB();
    }
Run Code Online (Sandbox Code Playgroud)
相比于:
    e0.ifExist(Element::actionA).ifNotExist(Element::actionB);
    e1.ifExist(Element::actionC);
    e2.ifExist(Element::actionD);
    e3.ifExist(Element::actionB);
Run Code Online (Sandbox Code Playgroud)
哪个更好?并且,oops,你注意到在传统的if子句代码中,有一个错误:
if (e1.exist()) {
    e0.actionC(); // Actually e1
}
Run Code Online (Sandbox Code Playgroud)
我想如果我们使用lambda,我们可以避免这个错误!
Joo*_*gen 33
因为它几乎但不是真正匹配Optional,也许您可能会重新考虑逻辑:
Java 8的表达能力有限:
Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);
System.out.println(element.orElse(DEFAULT_ELEM));
Run Code Online (Sandbox Code Playgroud)
这里map可能会限制元素的视图:
element.map(el -> el.mySpecialView()).ifPresent(System.out::println);
Run Code Online (Sandbox Code Playgroud)
Java 9:
element.ifPresentOrElse(el -> System.out.println("Present " + el,
                        () -> System.out.println("Not present"));
Run Code Online (Sandbox Code Playgroud)
通常,两个分支是不对称的.
Mic*_*ael 19
它被称为"流畅的界面".只需更改返回类型并return this;允许您链接方法:
public MyClass ifExist(Consumer<Element> consumer) {
    if (exist()) {
        consumer.accept(this);
    }
    return this;
}
public MyClass ifNotExist(Consumer<Element> consumer) {
    if (!exist()) {
        consumer.accept(this);
    }
    return this;
}
Run Code Online (Sandbox Code Playgroud)
你可以得到一点点发烧友并返回一个中间类型:
interface Else<T>
{
    public void otherwise(Consumer<T> consumer); // 'else' is a keyword
}
class DefaultElse<T> implements Else<T>
{
    private final T item;
    DefaultElse(final T item) { this.item = item; }
    public void otherwise(Consumer<T> consumer)
    {
        consumer.accept(item);
    }
}
class NoopElse<T> implements Else<T>
{
    public void otherwise(Consumer<T> consumer) { }
}
public Else<MyClass> ifExist(Consumer<Element> consumer) {
    if (exist()) {
        consumer.accept(this);
        return new NoopElse<>();
    }
    return new DefaultElse<>(this);
}
Run Code Online (Sandbox Code Playgroud)
样品用法:
element.ifExist(el -> {
    //do something
})
.otherwise(el -> {
    //do something else
});
Run Code Online (Sandbox Code Playgroud)
        Era*_*ran 12
您可以使用一个需要两个消费者的方法:
public void ifExistOrElse(Consumer<Element> ifExist, Consumer<Element> orElse) {
    if (exist()) {
        ifExist.accept(this);
    } else {
        orElse.accept(this);
    }
}
Run Code Online (Sandbox Code Playgroud)
然后用:
element.ifExistOrElse(
  el -> {
    // Do something
  },
  el -> {
    // Do something else
  });
Run Code Online (Sandbox Code Playgroud)
        element.ifExist(() -> { ... }).otherElementMethod();
          ^                      ^
        control flow method     business logic method
Run Code Online (Sandbox Code Playgroud)
(2) 目前尚不清楚控制流方法(如ifExist、ifNotExist)之后的方法应如何表现。它们应该始终执行还是仅在条件下调用(类似于ifExist)?
(3) 顾名思义ifExist是终端操作,所以没有返回任何内容 - void。一个很好的例子void ifPresent(Consumer)来自Optional.
我会编写一个完全独立的类,该类独立于任何具体类和任何特定条件。
该接口很简单,由两个无上下文控制流方法 -ifTrue和组成ifFalse。
可以有几种方法来创建Condition对象。element我为您的实例(例如)和条件(例如)编写了一个静态工厂方法Element::exist。
public class Condition<E> {
    private final Predicate<E> condition;
    private final E operand;
    private Boolean result;
    private Condition(E operand, Predicate<E> condition) {
        this.condition = condition;
        this.operand = operand;
    }
    public static <E> Condition<E> of(E element, Predicate<E> condition) {
        return new Condition<>(element, condition);
    }
    public Condition<E> ifTrue(Consumer<E> consumer) {
        if (result == null)
            result = condition.test(operand);
        if (result)
            consumer.accept(operand);
        return this;
    }
    public Condition<E> ifFalse(Consumer<E> consumer) {
        if (result == null)
            result = condition.test(operand);
        if (!result)
            consumer.accept(operand);
        return this;
    }
    public E getOperand() {
        return operand;
    }
}
Run Code Online (Sandbox Code Playgroud)
此外,我们可以集成Condition到Element:
class Element {
    ...
    public Condition<Element> formCondition(Predicate<Element> condition) {
        return Condition.of(this, condition);
    }
}
Run Code Online (Sandbox Code Playgroud)
我提倡的模式是:
Element;一起工作Condition;Condition;Element;Element.Condition通过以下方式获取Condition.of:
Element element = new Element();
Condition.of(element, Element::exist)
             .ifTrue(e -> { ... })
             .ifFalse(e -> { ... })
         .getOperand()
             .otherElementMethod();
Run Code Online (Sandbox Code Playgroud)
Condition通过以下方式获取Element#formCondition:
Element element = new Element();
element.formCondition(Element::exist)
           .ifTrue(e -> { ... })
           .ifFalse(e -> { ... })
       .getOperand()
           .otherElementMethod();
Run Code Online (Sandbox Code Playgroud)
对于其他测试方法,想法保持不变。
Element element = new Element();
element.formCondition(Element::isVisible);
element.formCondition(Element::isEmpty);
element.formCondition(e -> e.hasAttribute(ATTRIBUTE));
Run Code Online (Sandbox Code Playgroud)
这是重新考虑代码设计的一个很好的理由。两个片段都不是很好。
想象一下您需要actionC在e0.exist(). 方法引用将如何Element::actionA更改?
它将被转回 lambda:
e0.ifExist(e -> { e.actionA(); e.actionC(); });
Run Code Online (Sandbox Code Playgroud)
除非你将actionAand包装actionC在一个方法中(这听起来很糟糕):
e0.ifExist(Element::actionAAndC);
Run Code Online (Sandbox Code Playgroud)
现在的 lambda 比以前更不“可读” if。
e0.ifExist(e -> {
    e0.actionA();
    e0.actionC();
});
Run Code Online (Sandbox Code Playgroud)
但我们要付出多少努力才能做到这一点呢?我们将付出多少努力来维护这一切?
if(e0.exist()) {
    e0.actionA();
    e0.actionC();
}
Run Code Online (Sandbox Code Playgroud)