Java:用 lambda 表达式替换 switch。值得?
Java: replace switch with lambdas. Worth it?
在检查事件时,将代码块与 switch 或 if 结合使用是很常见的事情。它可以是简洁的代码,但看起来仍然比需要的行多,并且可以使用 lambdas 进行简化。
阻止如果:
if(action == ACTION_1){
doAction1();
} else if(action == ACTION_2){
doAction2();
} else {
doDefaultAction();
}
带开关的块:
switch(action){
case ACTION_1:
doAction1();
break;
case ACTION_2:
doAction2();
break;
default:
doDefaultAction();
}
使用以下实用程序 class With
使用 lambda 进行阻止:
with(action)
.when(ACTION_1, this::doAction1)
.when(ACTION_2, this::doAction2)
.byDefault(this::doDefaultAction)
使用 lambda 的代码更少,但问题是:它比其他的更容易阅读吗?更容易维护?关于性能 lambdas 是最差的,但对于性能不重要的情况,lambdas 版本比 switch/if 块短。
那么,你怎么看呢?也许有比这更短的 Kotlin 方法,我试着只关注 java,我喜欢 Kotlin,但编译对于我的项目来说仍然太慢了。
当块必须 return 特定值时,可以使用类似的实用程序 class。
仅供参考,lambda 的 class 在这里,我没有检查错误,只是为了这个例子快速完成:
public class With<T> {
private final T id;
private boolean actionFound;
private With(T id) {
this.id = id;
}
public static <T> With<T> with(T id) {
return new With<>(id);
}
public With<T> when(T expectedId, Action action) {
if (!actionFound && id == expectedId) {
actionFound = true;
action.execute();
}
return this;
}
public void byDefault(Action action) {
if (!actionFound) {
action.execute();
}
}
@FunctionalInterface
interface Action {
void execute();
}
}
开关更加灵活,您可以使用不同数量的参数调用函数,或者调用多个函数。您还可以更轻松地表示两种情况何时会导致相同的操作。它更快的事实只是一个好处。
所以从这个意义上说,我不确定你的 With
class 到底在添加什么。
但是,switch 可以使用的类型数量有限。也许你的 With
class 如果你要传递它谓词而不是执行简单的引用相等,那么你的 With
class 会被证明更有用,例如:
public With<T> when(Predicate<T> expected, Action action) {
if (!actionFound && expected.test(id)) {
actionFound = true;
action.execute();
}
return this;
}
示例用法:
final String test = "test";
with(test)
.when(String::isEmpty, this::doAction1)
.when(s -> s.length() == 3, this::doAction2)
.byDefault(this::doDefaultAction);
replace switch with lambdas. Worth it?
没有
因为在 OO 语言中 switch
或 if
/else
级联的替换是 多态性 ,而不是 "fluent API".
正如一对夫妇所说,用复合方法代替 switch
效率较低。根据您的用例,使用您的实现甚至可能是值得的。
有趣的是,Oracle 实际上计划在 switch
语句中实施 lambda,如 this recent JEP.
中所示
示例:
String formatted = switch (s) {
case null -> "(null)";
case "" -> "(empty)";
default -> s;
}
执行此操作的一个选项是声明 static final Map<T, Action> EXPECTED_ID_TO_ACTION
。然后你就可以 EXPECTED_ID_TO_ACTION.getOrDefault(actionId, DEFAULT_ACTION).execute()
,把丑陋的 switch
或多个 if
变成单行。
在检查事件时,将代码块与 switch 或 if 结合使用是很常见的事情。它可以是简洁的代码,但看起来仍然比需要的行多,并且可以使用 lambdas 进行简化。
阻止如果:
if(action == ACTION_1){
doAction1();
} else if(action == ACTION_2){
doAction2();
} else {
doDefaultAction();
}
带开关的块:
switch(action){
case ACTION_1:
doAction1();
break;
case ACTION_2:
doAction2();
break;
default:
doDefaultAction();
}
使用以下实用程序 class With
使用 lambda 进行阻止:
with(action)
.when(ACTION_1, this::doAction1)
.when(ACTION_2, this::doAction2)
.byDefault(this::doDefaultAction)
使用 lambda 的代码更少,但问题是:它比其他的更容易阅读吗?更容易维护?关于性能 lambdas 是最差的,但对于性能不重要的情况,lambdas 版本比 switch/if 块短。
那么,你怎么看呢?也许有比这更短的 Kotlin 方法,我试着只关注 java,我喜欢 Kotlin,但编译对于我的项目来说仍然太慢了。
当块必须 return 特定值时,可以使用类似的实用程序 class。
仅供参考,lambda 的 class 在这里,我没有检查错误,只是为了这个例子快速完成:
public class With<T> {
private final T id;
private boolean actionFound;
private With(T id) {
this.id = id;
}
public static <T> With<T> with(T id) {
return new With<>(id);
}
public With<T> when(T expectedId, Action action) {
if (!actionFound && id == expectedId) {
actionFound = true;
action.execute();
}
return this;
}
public void byDefault(Action action) {
if (!actionFound) {
action.execute();
}
}
@FunctionalInterface
interface Action {
void execute();
}
}
开关更加灵活,您可以使用不同数量的参数调用函数,或者调用多个函数。您还可以更轻松地表示两种情况何时会导致相同的操作。它更快的事实只是一个好处。
所以从这个意义上说,我不确定你的 With
class 到底在添加什么。
但是,switch 可以使用的类型数量有限。也许你的 With
class 如果你要传递它谓词而不是执行简单的引用相等,那么你的 With
class 会被证明更有用,例如:
public With<T> when(Predicate<T> expected, Action action) {
if (!actionFound && expected.test(id)) {
actionFound = true;
action.execute();
}
return this;
}
示例用法:
final String test = "test";
with(test)
.when(String::isEmpty, this::doAction1)
.when(s -> s.length() == 3, this::doAction2)
.byDefault(this::doDefaultAction);
replace switch with lambdas. Worth it?
没有
因为在 OO 语言中 switch
或 if
/else
级联的替换是 多态性 ,而不是 "fluent API".
正如一对夫妇所说,用复合方法代替 switch
效率较低。根据您的用例,使用您的实现甚至可能是值得的。
有趣的是,Oracle 实际上计划在 switch
语句中实施 lambda,如 this recent JEP.
示例:
String formatted = switch (s) {
case null -> "(null)";
case "" -> "(empty)";
default -> s;
}
执行此操作的一个选项是声明 static final Map<T, Action> EXPECTED_ID_TO_ACTION
。然后你就可以 EXPECTED_ID_TO_ACTION.getOrDefault(actionId, DEFAULT_ACTION).execute()
,把丑陋的 switch
或多个 if
变成单行。