使用 Java lambda 而不是 'if else'

2022-09-01 04:18:42

在Java 8中,我有以下代码:

if(element.exist()){
    // Do something
}

我想转换为 lambda 样式,

element.ifExist(el -> {
    // Do something
});

使用如下方法:ifExist

public void ifExist(Consumer<Element> consumer) {
    if (exist()) {
        consumer.accept(this);
    }
}

但现在我还有其他案例可以调用:

element.ifExist(el -> {
    // Do something
}).ifNotExist(el -> {
    // Do something
});

我可以写一个类似的,我希望它们是相互排斥的(如果条件为真,则无需检查,因为有时,exist()方法需要太多的工作量来检查),但我总是需要检查两次。我该如何避免这种情况?ifNotExistexistifNotExist

也许“存在”这个词让有人误解了我的想法。你可以想象我还需要一些方法:

ifVisible()
ifEmpty()
ifHasAttribute()

很多人说这是个坏主意,但是:

在Java 8中,我们可以使用lambda forEach而不是传统的循环。在编程中,是两个基本的流程控件。如果我们可以使用lambda进行循环,那么为什么使用lambda来表示坏主意?forforifforif

for (Element element : list) {
    element.doSomething();
}

list.forEach(Element::doSomething);

在Java 8中,有ifPresent,类似于我对ifExist的想法:Optional

Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);

关于代码维护和可读性,如果我有以下代码,其中包含许多重复的简单子句,您会怎么想?if

if (e0.exist()) {
    e0.actionA();
} else {
    e0.actionB();
}

if (e1.exist()) {
    e0.actionC();
}

if (e2.exist()) {
    e2.actionD();
}

if (e3.exist()) {
    e3.actionB();
}

与以下产品相比:

e0.ifExist(Element::actionA).ifNotExist(Element::actionB);
e1.ifExist(Element::actionC);
e2.ifExist(Element::actionD);
e3.ifExist(Element::actionB);

哪个更好?而且,哎呀,你有没有注意到,在传统的子句代码中,有一个错误:if

if (e1.exist()) {
    e0.actionC(); // Actually e1
}

我认为如果我们使用lambda,我们可以避免这个错误!


答案 1

由于它几乎但并不完全匹配可选,也许您可能会重新考虑逻辑:

Java 8 具有有限的表现力:

Optional<Elem> element = ...
element.ifPresent(el -> System.out.println("Present " + el);
System.out.println(element.orElse(DEFAULT_ELEM));

此处可能会限制元素的视图:map

element.map(el -> el.mySpecialView()).ifPresent(System.out::println);

Java 9:

element.ifPresentOrElse(el -> System.out.println("Present " + el,
                        () -> System.out.println("Not present"));

一般来说,这两个分支是不对称的。


答案 2

它被称为“流畅的界面”。只需更改返回类型,即可链接方法: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;
}

你可以变得更花哨,并返回一个中间类型:

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);
}

示例用法:

element.ifExist(el -> {
    //do something
})
.otherwise(el -> {
    //do something else
});

推荐