我正在研究程序的一部分(关于语音识别和遥控车),其中代码transmit(XXXXX); disableAutoMode();
重复多次。出于好奇心的缘故,我想将其转换为类似于var f = p -> transmit(p); disableAutoMode();
的lambda函数(原谅var
;我不知道表达式的类型是什么)然后在一个函数中调用它类似于此的方式:f("s");
,f("a");
和f("f");
或与f.call("s");
,f.call("a");
和f.call("f");
类似的内容。
在Java中使用简单的lambda函数的正确语法是什么,类似于我上面描述的? (我应该把它放在什么类型而不是说var
?)
以下是代码块,如果你很好奇:
@Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i("onresult",text);
ToastMaster(text);
switch (text) {
case "forward":
case "go forward":
transmit("f");
disableAutoMode();
break;
case "go back":
case "go backward":
case "back":
case "backward":
case "reverse":
transmit("b");
disableAutoMode();
break;
case "skid left":
case "go left":
transmit("l");
disableAutoMode();
break;
case "skid right":
case "go right":
transmit("r");
disableAutoMode();
break;
case "turn left":
transmit("q");
disableAutoMode();
break;
case "turn right":
transmit("e");
disableAutoMode();
break;
case "reverse left":
transmit("z");
disableAutoMode();
break;
case "reverse right":
transmit("x");
disableAutoMode();
break;
case "stop":
disableAutoMode();
break;
case "automatic":
toggleAutoMode(null);
break;
case "enable automatic mode":
enableAutoMode();
break;
case "disable automatic mode":
disableAutoMode();
break;
}
}
}
答案 0 :(得分:8)
更加雄心勃勃的重构将建立在将代码转换为数据的基础之上。 lambdas的所有原则,将switch语句从代码转换为数据。怎么样:
// One-time setup of the machine
Map<String, Consumer<String>> actions = new HashMap<>();
actions.put("go forward", x -> { transmit(x); disableAutoMode(); });
actions.put(...)
...
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i("onresult",text);
ToastMaster(text);
Consumer<String> action = actions.get(text);
if (action != null)
action.accept(text);
}
}
答案 1 :(得分:3)
在这种情况下,您需要Consumer
。
Consumer<String> function = (x) -> { transmit(x); disableAutoMode(); };
function.accept("hello!");
但是我不确定你为什么要在这里使用lambda表达式,你可以创建一个普通的旧方法并调用它。
如果您使用的是更有意义的重构,则可以选择切换到String
,Action/Runnable
的地图。虽然你最终会得到更多的代码,但重构的目标不是使它变得更小&#34;但要使其更具可读性/可维护性。通过将每个动作分成它自己的小型自包含类,每个动作都可以通过最少的设置进行单独测试。每个动作都可以重复使用(因为它只是一个类)。通过良好的命名策略,读者可以清楚地知道发生了什么,而无需深入了解大型switch语句。
答案 2 :(得分:2)
调用lambda比使用简单的辅助方法更乏味:
private void m(String x) {
transmit(x);
disableAutoMode();
}
(更详细)替代方案是使用lambdas:
Consumer<String> consumer = (x) -> {
transmit(x);
disableAutoMode();
};
然后将其称为
consumer.accept("f");
答案 3 :(得分:0)
你想做什么,确实可以使用lambda表达式,但保存不会那么大:
@Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i("onresult",text);
ToastMaster(text);
Consumer<String> transmitDisable=s->{ transmit(s); disableAutoMode(); };
switch (text) {
case "forward": case "go forward":
transmitDisable.accept("f");
break;
case "go back": case "go backward": case "back":
case "backward": case "reverse":
transmitDisable.accept("b");
break;
case "skid left": case "go left":
transmitDisable.accept("l");
break;
case "skid right": case "go right":
transmitDisable.accept("r");
break;
case "turn left": transmitDisable.accept("q"); break;
case "turn right": transmitDisable.accept("e"); break;
case "reverse left": transmitDisable.accept("z"); break;
case "reverse right": transmitDisable.accept("x"); break;
case "stop": disableAutoMode(); break;
case "automatic": toggleAutoMode(null); break;
case "enable automatic mode": enableAutoMode(); break;
case "disable automatic mode": disableAutoMode(); break;
}
}
}
但是,如果你考虑Java不常用的代码流控制结构,你也可以删除没有lambda表达式的代码重复:
@Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i("onresult",text);
ToastMaster(text);
transmitAndDisable: {
final String toTransmit;
switch (text) {
case "forward": case "go forward": toTransmit="f"; break;
case "go back": case "go backward": case "back":
case "backward": case "reverse": toTransmit="b"; break;
case "skid left": case "go left": toTransmit="l"; break;
case "skid right": case "go right": toTransmit="r"; break;
case "turn left": toTransmit="q"; break;
case "turn right": toTransmit="e"; break;
case "reverse left": toTransmit="z"; break;
case "reverse right": toTransmit="x"; break;
case "stop": disableAutoMode(); break transmitAndDisable;
case "automatic": toggleAutoMode(null); break transmitAndDisable;
case "enable automatic mode": enableAutoMode(); break transmitAndDisable;
case "disable automatic mode": disableAutoMode(); break transmitAndDisable;
default: break transmitAndDisable;
}
transmit(toTransmit);
disableAutoMode();
}
}
}
结构可能不那么容易理解,但请注意如何将toTransmit
声明为final
有很大帮助。因为它是final
,所以无法使用回退值进行初始化,这意味着获取共享transmit(…); disableAutoMode();
代码的每个备选方案都必须将变量初始化一次。
换句话说,
transmitAndDisable
指定break
标签,编译器将立即大喊,因为toTransmit
尚未初始化toTransmit
两次transmitAndDisable
错误地指定break
标签,那么优秀的编译器将发出有关未使用的作业的警告