除了保存代码行之外,lambda表达式还有什么用处吗?
lambda提供的特殊功能是否解决了不容易解决的问题?我见过的典型用法是代替写这个:
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
Run Code Online (Sandbox Code Playgroud)
我们可以使用lambda表达式来缩短代码:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
Run Code Online (Sandbox Code Playgroud) Loop.times(5, () -> {
System.out.println("looping");
});
Run Code Online (Sandbox Code Playgroud)
哪些有效编译到?
for(int i = 0; i < 5; i++)
System.out.println("looping");
Run Code Online (Sandbox Code Playgroud)
或类似的东西
new CallableInterfaceImpl(){
public void call(){
for(int i = 0; i < 5; i++)
System.out.println("looping");
}
}.call();
Run Code Online (Sandbox Code Playgroud)
它会替换(内联类),还是实际创建一个匿名类?
我听说lambdas即将到达你附近的Java(J8).我在一些博客上找到了一个例子:
SoccerService soccerService = (teamA, teamB) -> {
SoccerResult result = null;
if (teamA == teamB) {
result = SoccerResult.DRAW;
}
else if(teamA < teamB) {
result = SoccerResult.LOST;
}
else {
result = SoccerResult.WON;
}
return result;
};
Run Code Online (Sandbox Code Playgroud)
所以马上就开始了:
teamA和teamB类型?或者不是它们(就像一些奇怪的泛型)?我最近遇到了EclipseCon 2014 的演示文稿,在第5页上他们说"Lambda表达式允许您将代码视为数据".
我也遇到了这个示例代码
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
Run Code Online (Sandbox Code Playgroud)
来自Richard Warburton的"Java 8 Lambdas:实用功能编程",他说
"这实际上是使用代码作为数据的一个例子 - 我们为按钮提供了一个表示动作的对象."
代码作为数据对于Lambda表达式和/或匿名内部类意味着什么?
首先,请耐心等待.大部分时间我在Scala(有时只在JVM端)或其他语言工作,所以我的Java(8)知识有点受限!
我必须重构的代码充满了空检查.我想让一些pojo的属性设置/覆盖更好一点,并且很高兴能够使用Java 8来完成工作.
所以我创造了这个:
private <T> void setOnlyIfNotNull(final T newValue, Consumer<T> setter) {
if(newValue != null) {
setter.accept(newValue);
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
setOnlyIfNotNull(newUserName, user::setName);
Run Code Online (Sandbox Code Playgroud)
junit4-test看起来像这样:
@Test
public void userName_isOnlyUpdated_ifProvided() {
User user = new User("oldUserName");
UserUpdateRequest request = new UserUpdateRequest().withUserName("newUserName");
service.updateUser(user, request); // This calls setOnlyIfNotNull behind the curtain. And it does invoke the setter ONLY once!
assertThat(user.getUserName()).isEqualTo("newUserName");
}
Run Code Online (Sandbox Code Playgroud)
这很有效.在我请同事进行代码审查之前,我对自己很满意.在解释我做了什么之后,他详细说明了他认为这不起作用,因为函数仍然没有Java中的一等公民,而User-pojo没有扩展FunctionalInterface.接口也是在类级别而不是功能级别上提供的.
现在我想知道,为什么测试工作,我在这里滥用了什么?天真我只是想象Java编译器知道setter的T setT(T value)签名与a相同Consumer<T>.
编辑:详细说明一下:如果我将测试更改为失败,例如,assertThat(user.getUserName()).isEqualTo("Something");如果失败,则会按预期进行compareFailure!
因此,我中的函数程序员喜欢像python这样的语言,它们将函数视为一等公民。看起来Java 8承受了压力,而诸如lambda表达式和方法引用之类的“已实现的”东西则被淘汰了。
我的问题是,Java是否正在使用一流的函数,或者这真的只是语法糖,以减少实现匿名类/接口(如可运行的接口)所需的代码量?(我的肠子说后者)。
我理想的情况
Map<String,DoubleToDoubleFunc> mymap = new HashMap<String,DoubleToDoubleFunc>();
...
mymap.put("Func 1", (double a, double b) -> a + b);
mymap.put("Func 2", Math::pow);
...
w = mymap.get("Func 1")(y,z);
x = mymap.get("Func 2")(y,z);
Run Code Online (Sandbox Code Playgroud)