Lambda表达式是可以简化函数式接口的变量与形参赋值的语法。而方法引用和构造器引用是为了简化Lambda表达式的。当Lambda表达式满足一些特殊的情况时,还可以再简化:
方法引用的语法格式:
(1)实例对象名::实例方法
(2)类名::静态方法
(3)类名::实例方法
构造器引用的语法格式:
类名::new
数组类型名::new
情况:
1)Lambda体只有一句语句,并且是通过调用一个对象的/类现有的方法来完成的
例如:System.out对象,调用println()方法来完成Lambda体
Math类,调用random()静态方法来完成Lambda体 ()
(2)并且Lambda表达式的形参正好是给该方法的实参
例如:t->System.out.println(t)
() -> Math.random() 都是无参
方法引用
(1)实例对象名::实例方法
(2)类名::静态方法
(3)类名::实例方法
说明
::称为方法引用操作符(两个:中间不能有空格,而且必须英文状态下半角输入)
Lambda表达式的形参列表,全部在Lambda体中使用上了,要么是作为调用方法的对象,要么是作为方法的实参。
在整个Lambda体中没有额外的数据。
lambda表达式 简化 匿名内部类
方法/构造器引用:简化lambda表达式
如何引用:
对象名::方法名 方法引用
类名::方法名
类名::new 构造器引用当重写方法参数的形参 与 重写方法体内 对象调用方法的形参完全重合时
@Test
public void test4(){
// Runnable r = () -> System.out.println("hello lambda");
Runnable r = System.out::println;//打印空行
//不能简化方法引用,因为"hello lambda"这个无法省略
}能使用方法引用必须要求 Runnable r = ()中的形参与System.out.println("hello lambda");方法形参完全相同,可以省略。
@Test
public void test02(){
String [] arr = {"world", "java","Hello"};
/*Arrays.sort(arr, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
});*/
//用方法引用简化
/*
* Lambda表达式的形参,第一个(例如:s1),正好是调用方法的对象,剩下的形参(例如:s2)正好是给这个方法的实参
*/
// Arrays.sort(arr,(n,m) -> n.compareToIgnoreCase(m));
// Arrays.sort(arr,String::compareToIgnoreCase);
for (String s : arr) {
System.out.println("s = " + s);
}
}
@Test
public void test03() {
Person p = new Person();
// System.out.println("p.getName() = " + p.getName());
/* Supplier<String> s = new Supplier<String>() {
@Override
public String get() {
return p.getName();
}
};*/
// Supplier<String> s = () -> p.getName();
//形参列表完全相同
Supplier<String> s = p::getName;
String s1 = s.get();
System.out.println("s1 = " + s1);
}
@Test
public void test02(){
Integer [] arr = {10, -1, 90, 100, 20, 30, -9};
System.out.println("Arrays.toString(arr) = " + Arrays.toString(arr));
/* Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// compare(Integer o1, Integer o2) 与 Integer.compare(o1,o2);的形参完全相同
return Integer.compare(o1,o2);
}
});*/
Arrays.sort(arr,Integer::compareTo);
System.out.println("Arrays.toString(arr) = " + Arrays.toString(arr));
}
@Test
public void test01(){
ArrayList<String> list = new ArrayList<>();
list.add("李白");
list.add("杜甫");
list.add("王安石");
list.add("李商隐");
//当重写方法参数的形参与重写方法体内对象调用方法的形参完全重合时
//list.forEach((s) -> System.out.println(s));
list.forEach(System.out::println);
}
构造器引用
(1)当Lambda表达式是创建一个对象,并且满足Lambda表达式形参,正好是给创建这个对象的构造器的实参列表。
(2) 当Lambda表达式是创建一个数组对象,并且满足Lambda表达式形参,正好是给创建这个数组对象的长度
构造器引用的语法格式:
类名::new
数组类型名::new
public class TestMethodReference {
@Test
public void teset04() {
//需求:获取n个int[] 数组
//传统Lambda实现
Function<Integer,int[]> function = (i) -> new int[i];
int[] apply = function.apply(5);
System.out.println(apply.length); // 5
//数组类型引用实现
function = int[] ::new;
apply = function.apply(10);
System.out.println(apply.length); // 10
}
//这个方法是模仿HashMap中,把你指定的数组的长度纠正为2的n次方的代码
//createArray()的作用是,创建一个长度为2的n次方的数组
public <R> R[] createArray(Function<Integer,R[]> fun,int length){
int n = length - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
length = n < 0 ? 1 : n + 1;
return fun.apply(length);
}
@Test
public void test3(){
/*
* Function是一个函数式接口,可以用Lambda表达式赋值
* Function<T,R>的抽象方法 R apply(T t)
*
* createArray这个方法中用的是Function<Integer,R[]> fun。说明T类型已经指定为Integer
* 说明
*/
// Function<Integer,String[]> f = (Integer len) -> new String[len];
//因为Lambda体是在创建一个数组对象完成的,而且Lambda表达式的形参正好是创建数组用的长度
//通过构造器引用省略
Function<Integer,String[]> f = String[]::new;
String[] array = createArray(f, 10);
System.out.println(array.length);//16
}
@Test
public void teset02() {
Stream<String> stream = Stream.of("1.0","2.3","4.4");
// Stream<BigDecimal> stream2 = stream.map(num -> new BigDecimal(num));
Stream<BigDecimal> stream2 = stream.map(BigDecimal::new);
}
@Test
public void test1(){
// Supplier<String> s = () -> new String();//通过供给型接口,提供一个空字符串对象
//构造器引用
Supplier<String> s = String::new;//通过供给型接口,提供一个空字符串对象
}
}