lambda与方法引用如果说lambda表示式本质上是将方法作为对象进行处理,那么方法引用就是将现有方法作为lambda表达式进行处理
我们首先来看下面这个例子
import java.util.function.Consumer;
import java.util.stream.Stream;
public class Test01 {
public static void main(String[] args) {
// 使用lambda表达式,将流的所有元素打印到标准输出
Stream.of(3, 1, 4, 1, 5, 9).forEach(x -> System.out.println(x));
// 使用方法引用的方式,将流的所有元素打印到标准输出
// 双冒号表示法在system.out实例上提供了对println方法的引用,属于PrintStream类型的引用。方法引用的末尾无需括号
Stream.of(3, 1, 4, 1, 5, 9).forEach(System.out::println);
// 将方法引用赋给函数式接口,将流的所有元素打印到标准输出
Consumer printer = System.out::println;
Stream.of(3, 1, 4, 1, 5, 9).forEach(printer);
// 在静态方法中使用方法引用
Stream.generate(Math::random) // 静态方法
.limit(10).forEach(System.out::println); // 实例方法
}
}与lambda语法相比,方法引用具有以下2个优点,使得代码更易于阅读首先,方法引用往往更短
其次,方法引用通常包括含有该方法的类的名称
语法
方法引用包括以下三种方式object::instanceMethod引用特定对象的实例方法,如System.out::println
Class::staticMethod引用静态方法,如:Math::max
Class::instanceMethod调用特定类型的任意对象的实例方法,如String::length
lambda表达式和方法引用在任何情况下都不能脱离上下文存在,有时候为避免歧义,经常在方法引用的左侧使用this或super以对象引用为例,上下文提供了方法的参数;对于System.out::println,等效的lambda表达式为:x -> System.out.println(x);
上下文提供了x的值,它被用作方法的参数
静态方法max与之类似//相当于Math::max
(x,y)->Math.max(x,y)
此时,需要上下文提供两个参数,lambda表达式返回较大的数
通过类名调用实例方法,等效的lambda表达式为://相当于String::length
x -> x.length()
此时上下文提供x的值,用作方法的目标而非参数
如果通过类名引用一个传入多个参数的方法,则上下文提供的第一个元素将作为方法的目标,其他元素作为方法的参数
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream接口定义的sorted方法传入Comparator作为参数 其单一抽象方法为int compare(String other)
* sorted方法将每对字符串提供给比较器,并提供返回整数的符号对它们进行排序
*/
public class Test02 {
public static void main(String[] args) {
List strings = Arrays.asList("this", "is", "a", "list", "of", "strings");
List sorted1 = strings.stream()
.sorted((s1, s2) -> s1.compareTo(s2))
// 调用第一个参数s1的compareTo方法,并使用第二个元素s2作为该方法的参数
.collect(Collectors.toList());
List sorted2 = strings.stream()
.sorted(String::compareTo)
.collect(Collectors.toList());
}
}在流处理中,如果需要处理一系列的输入,则会频繁的使用方法引用中的类名来访问实例方法,如下例子
import java.util.stream.Stream;
/**
* 程序调用length方法并将每个字符串转换成一个整数打印出来
*/
public class Test03 { public static void main(String[] args) {
Stream.of("this", "is", "a", "list", "of", "strings")
.map(String::length)// 通过类名访问实例方法
.forEach(System.out::println);
// 通过对象引用访问实例方法
//等效的lambda表示式
Stream.of("this", "is", "a", "list", "of", "strings")
.map(s -> s.length())
.forEach(x -> System.out.println(x));
}
}