Pan*_*s K 10 java performance if-statement optional java-8
您好,我有两个代码示例
if / else if / else语句
private Object getObj(message) {
if (message.getA() != null)
return message.getA();
else if (message.getB() != null)
return message.getB();
else if (message.getC() != null)
return message.getC();
else return null;
}
Run Code Online (Sandbox Code Playgroud)
可选陈述
private Optional<Object> wrap(Object o){
return Optional.ofNullable(o);
}
private Object getObj(message) {
return wrap(message.getA())
.orElseGet(() -> wrap(message.getB())
.orElseGet(() -> wrap(message.getC())
.orElse(null)));
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,这两者在性能方面如何比较(我在实际代码中大约有15-20条if-else语句)?
值得重构代码的可读性和性能,还是滥用可选选项?
另外,如果if / else-if语句增长到100+,性能损失会是多少?
提前致谢
Lin*_*ica 16
不要将Optional
s用于条件逻辑。
它们被设计为从一种方法中返回,以指示可能不存在的值。
仅仅因为您可以将它们很好地链接成一行并不意味着它是可以理解的。您实际上也一无所获。性能开销可能很大。在最坏的情况下,N
将创建对象然后将其丢弃。只需呆在您的“正常” if-else
锁链上。
退一步,问自己为什么需要15-20 if-else语句,而不是寻找使当前代码更具可读性的方法。你能分解一些逻辑吗?为什么首先需要为具有多个可能具有不同类型的多个不同字段使用一个吸气剂?等等
还有第三种形式(允许有些变化)。
return Stream.<Supplier<Object>>of(message::getA, message::getB, message::getC)
.map(Supplier::get)
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
Run Code Online (Sandbox Code Playgroud)
目前可能是最不灵活和效率最高的,但是很清楚。
如果您的目标是精简代码,则使用三元链接。性能可能与一系列 if-then-else 语句的性能相同。
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
Run Code Online (Sandbox Code Playgroud)
正如Lino的答案正确指出的那样,您正试图Optional
超越其最初的设计目的(在 lambdas 和流中返回值)。通常最好Optional
仅与return
语句一起使用,并且仅当您要明确 null 是要返回的有效值时才使用。请参阅Brian Goetz 的这个答案。
甲三元运算符是一个冷凝if-then-else
,组合成一衬垫。
result = test ? valueToUseIfTestIsTrue : valueToUseIfTestIsFalse
Run Code Online (Sandbox Code Playgroud)
例子:
Color color = isPrinterMonochrome ? Color.GREY : Color.GREEN ;
Run Code Online (Sandbox Code Playgroud)
使用三元语句链。
所以这:
if ( this.getA() != null )
return this.getA();
else if ( this.getB() != null )
return this.getB();
else if ( this.getC() != null )
return this.getC();
else return null;
Run Code Online (Sandbox Code Playgroud)
……变成这样:
return
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
Run Code Online (Sandbox Code Playgroud)
示例代码。
public String getA ()
{
// return "A";
return null;
}
public String getB ()
{
// return "B";
return null;
}
public String getC ()
{
return "C";
// return null;
}
public String getABC ()
{
if ( this.getA() != null )
return this.getA();
else if ( this.getB() != null )
return this.getB();
else if ( this.getC() != null )
return this.getC();
else return null;
}
public String getABCTernary ()
{
return
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
}
Run Code Online (Sandbox Code Playgroud)
运行该示例代码。
String s = this.getABCTernary();
System.out.println( "s: " + s );
Run Code Online (Sandbox Code Playgroud)
C
这两者在性能方面的比较
Java 中的三元运算符是"short-circuiting",这意味着与测试结果匹配的左侧或右侧是唯一调用的代码。在我们这里的代码中,如果getA
返回非空值,则立即返回该值。对getB
和的进一步调用getC
永远不会执行。所以在这方面,链式三元的表现和级联 if-then-else 语句是一样的:first-match wins,不再调用。
如果您的意思是执行纳秒级的性能,我不知道。担心会落入过早优化的陷阱。现代 JVM 非常适合优化代码。
在我看来,经过大约20年的商业经验,我已经形成了一个观点:追求可读性是绝对愚蠢的,同时,故意编写复杂的代码是邪恶的。
我知道这完全违背了大众的观点。
然而,每个人都需要认识到这一点……
if
看法Optional
。无论我们所处的结构或情况如何,此类辩论都会发生。if
式方法性能更高的选项,那么阅读该代码的人就会习惯它并发现它更具可读性- 因为这是他们现在已经习惯的风格。所以,本质上:使用if
...不要使用它Optional
!