java核心技术卷I-lambda

lambda 表达式

lambda 表达式就是一个代码块, 以及必须传人代码的变量规范。

(String first, String second) -> first.length()- second.length()

如果代码要完成的计算无法放在一个表达式中,就可以像写方法一样,把这些代码放在 {}中,并包含显式的 return语句

(String first, String second) -> {
	if (first.length() < second.length()) return -1;
	else if (first.length() > second.length()) return 1;
	else return 0;
}

即使 lambda 表达式没有参数, 仍然要提供空括号,就像无参数方法一样:

 () -> { for (int i = 100;i >= 0;i-- ) System.out.println(i); }

如果方法只有一 参数, 而且这个参数的类型可以推导得出,那么甚至还可以省略小括号

ActionListener listener = event ->
System.out.println("The time is " + new Date()");
 // Instead of (event) -> . . . or (ActionEvent event) -> . . .

无需指定 lambda 表达式的返回类型。lambda 表达式的返回类型总是会由上下文推导得出

(String first, String second) -> first.length() - second.length()

如果一个 lambda 表达式只在某些分支返回一个值, 而在另外一些分支不返回值,这是不合法的。
在 Java 中, 对 lambda 表达式所能做的也只是能转换为函数式接口。
java.util.function 包中有一个尤其有用的接口 Predicate:

public interface Predicate<T> {
boolean test(T t); // Additional default and static methods
}

ArrayList 类有一个 removelf 方法, 它的参数就是一个 Predicate。这个接口专门用来传递lambda 表达式。例如,下面的语句将从一个数组列表删除所有 null 值:

list.removelf(e -> e == null);

方法引用

有时, 可能已经有现成的方法可以完成你想要传递到其他代码的某个动作。

Timer t = new Timer(1000, System.out::println);

表达式 System.out::println 是一个方法引用( method reference ), 它等价于 lambda 表达式

x 一> System.out.println(x)。

构造器引用

构造器引用与方法引用很类似,只不过方法名为 new。
假设你有一个字符串列表。可以把它转换为一个 Person 对象数组,为此要在各个字符串上调用构造器,调用如下:

ArrayList<String> names = . . .;
Stream<Person> stream = names.stream().map(Person::new);
List<Person> people = stream.col1ect(Collectors.toList());

Java 有一个限制,无法构造泛型类型 T 的数组。数组构造器引用对于克服这个限制很有
用。表达式 new T[n] 会产生错误,因为这会改为 new Object[n]。例如,假设我们需要一个 Person 对象数组。Stream 接口有一个 toArray 方法可以返回 Object 数组:

Object[] people = stream.toArray();

用户希望得到一个 Person 引用数组,而不是 Object 引用数组。流库利用构造器引用解决了这个问题。可以把 Person[]::new 传人 toArray 方法:

Person[] people = stream.toArray(Person[]::new):

lambda 表达式有 3个部分:
1 ) 一个代码块;
2 ) 参数;
3 ) 自由变量的值, 这是指非参数而且不在代码中定义的变量。
lambda 表达式中捕获的变量必须实际上是最终变量 ( effectively final)。实际上的最终变量是指, 这个变量初始化之后就不会再为它赋新值。在这里,text 总是指示同一个String 对象,所以捕获这个变量是合法的。不过,i 的值会改变,因此不能捕获i。

public static void repeat(String text, int count) {
	for (int i = 1; i <= count; i++) {
		ActionListener listener = event -> {
		 System.out.println(i + ": " + text);
		  // Error: Cannot refer to changing 
	    };
		new Timer(1000, listener).start();
	} 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

局外人一枚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值