Lambda表达式
大量培训机构课程资源,需要加V:【blwxzy_188】
一、基础用法
Lambda表达式的本质:作为函数式接口的实例
1.1、函数式接口
概念
- 当接口中只有一个抽象方法的时候,我们管这种接口叫做函数式接口
- 如果怕写错可以加上注解
@FunctionalInterface
来限定这个接口为函数式接口
1.1.1、java8中官方提供的四个常用的函数式接口
1.1.2、使用
当函数式接口中的抽象方法没有返回值,没有参数时
/**
* 语法结构一:无参无返回值
* @author Kingstart
* @create 2020-10-06 22:34
*/
public interface Interface01 {
void testMethod ();
}
class Demo01{
public static void main ( String[] args ) {
/*
Lambda表达式的本质是:,Lambda表达式就是一个函数式接口的实例
Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的参数列表
右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能。
*/
Interface01 t01 = () -> System.out.println ( "无参无返回值的抽象方法" );
t01.testMethod ();
}
}
当函数式接口中的抽象方法没有返回值,却有一个参数时
/**
* 语法结构2:有一个参数没返回值
* @author Kingstart
* @create 2020-10-06 22:44
*/
public interface Inteface02 {
void testMethd(int num);
}
class Demo02{
/*
1.当只有一个参数时,数据类型可以省略,因为lambda会自动推断出数据类型
2小括号也可以省略
3.参数名可以随便起
4.如果方法体只有一条实现语句,大括号也可以省略
*/
public static void main ( String[] args ) {
//Inteface02 t02 = (num) -> System.out.println ( "这是有一个参数,没有返回值的方法,参数为:" + num );
Inteface02 t02 = x -> System.out.println ( "这是有一个参数,没有返回值的方法,参数为:" + x );
t02.testMethd ( 10 );
}
当函数式接口中的抽象方法没有返回值,却有多个参数时
public interface Interface05 {
void test(int num1,int num2);
}
class Demo05{
public static void main ( String[] args ) {
Interface05 t05 = (x,y) -> System.out.println ("多个参数,没有返回值的实现,参数为" + x + " " + y );
t05.test ( 10,20 );
}
}
当函数式接口中的抽象方法有返回值,没有参数时
public interface Interface06 {
int test();
}
class Demo06{
public static void main ( String[] args ) {
Interface06 t06 = () -> 10;
t06.test ();
}
}
当函数式接口中的抽象方法有返回值,并且有一个参数时
/**
* 语法结构3:一个参数,有返回值
* @author Kingstart
* @create 2020-10-06 22:47
*/
public interface Interface03 {
int testMethod(int num);
}
class Demo03{
public static void main ( String[] args ) {
/*
如果方法体中有多条语句,大括号就不能省略
*/
/*Interface03 t03 = x -> {
System.out.println ("这是有一个参数并且有返回值的方法,参数为:" + x );
return 10;
};*/
//Interface03 t03 = x -> { return 10;};
Interface03 t03 = x -> 10;
System.out.println ( t03.testMethod ( 10 ) );
}
}
当函数式接口中的抽象方法有返回值,并且有多个参数时
/**
* 语法结构四:有多个参数,并且还有返回值
* @author Kingstart
* @create 2020-10-06 22:55
*/
//我们管接口中只有一个抽象方法的接口叫做函数式接口,如果怕定义错,可以使用注解@FunctionalInterface 来限定这个接口为函数式接口
@FunctionalInterface
public interface Interface04 {
int testMethod(int num1,int num2);
}
class Demo04{
public static void main ( String[] args ) {
/**
* 如果有多个参数,小括号就不能省略了
* 如果方法体有多条语句,大括号就不能省略了,如果只有返回值一条语句,return也可以省略
*/
/*Interface04 t04 = (x,y) -> {
System.out.println ("这是有多个参数,并且有返回值的方法,参数为" + x + " " + y );
return 100;
};*/
Interface04 t04 = (x,y) -> 100;
System.out.println ( t04.testMethod ( 10 , 20 ) );
}
}
1.1.3、总结
什么时候使用lambda表达式?
当对一个函数式接口实例化的时候,就可以使用。
什么时候使用给定的函数式接口?
当我们开发中需要定义一个函数式接口,先看官方提供的函数式接口能否满足自己的需求,如果满足,就不需要自己定义,直接使用即可。
二、方法引用
2.1、使用情景:
当要传递给lambda表达式的操作,已经实现了方法时,可以使用方法引用,来简化代码
2.2、格式:
类/对象::方法名
2.3、三种情况:
- 情况一:对象::实例方法(非静态方法)
- 情况二:类::静态方法
- 情况三:类::实例方法(非静态方法)
2.4、要求:
- 针对于情况一和情况二:函数式接口中的形参列表和返回值类型要和方法引用中的形参列表和返回值类型要一摸一样
- 针对于情况三:当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用方法的参数(或无参数)时:ClassName::methodName
2.5、示例:
/**
* 方法引用的使用
*
* Created by shkstart.
*/
public class MethodRefTest {
// 情况一:对象 :: 实例方法
//Consumer中的void accept(T t)
//PrintStream中的void println(T t)
@Test
public void test1() {
//最原始,匿名内部类的实现方式
Consumer<String> con = new Consumer<String> ( ) {
@Override
public void accept ( String s ) {
System.out.println (s + "去北京了");
}
};
con.accept ( "王阳明" );
System.out.println ("================");
Consumer<String> con1 = str -> System.out.println ( str + "又去北京了");
con1.accept ( "王阳明" );
System.out.println ("=================" );
//方法引用进行优化 优化之后直接输出的是参数 System.out 就是一个对象
Consumer<String> con2 = System.out::println;
con2.accept ( "王阳明" );
}
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2() {
Employee em = new Employee (10,"Tom",20,20000 );
//最原始匿名内部类的写法
Supplier<String> sup = new Supplier<String> ( ) {
@Override
public String get ( ) {
String name = em.getName ( );
return name;
}
};
System.out.println ( sup.get ( ) );
System.out.println ( );
//Lambda表达式的写法
Supplier<String> sup1 = () -> em.getName ();
System.out.println ( sup1.get ( ) );
System.out.println ( );
//方法引用进行优化
Supplier<String> sup2 = em::getName;
System.out.println ( sup2.get ( ) );
}
// 情况二:类 :: 静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
//最原始匿名内部类的实现
Comparator<Integer> com = new Comparator<Integer> ( ) {
@Override
public int compare ( Integer o1 , Integer o2 ) {
int compare = Integer.compare ( o1 , o2 );
return compare;
}
};
System.out.println ( com.compare ( 10 , 20 ) );
System.out.println ("=============" );
Comparator<Integer> com1 = (x,y) -> Integer.compare (x,y);
System.out.println ( com1.compare ( 20 , 21 ) );
System.out.println ("=============");
//方法引用的优化
Comparator<Integer> com2 = Integer::compare;
System.out.println ( com2.compare ( 20 , 21 ) );
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4() {
//最原始的实现方法,匿名内部类的方式
Function<Double,Integer> fun = new Function<Double, Integer> () {
@Override
public Integer apply ( Double d )
{
long round = Math.round ( d );
return (int) round;
}
};
System.out.println ( fun.apply ( 14.3 ) );
System.out.println ("=================");
//lambda表达式实现方式
Function<Double,Long> fun1 = d -> Math.round (d);
System.out.println ( fun1.apply ( 14.3 ) );
System.out.println ("==================");
//方法引用进行优化
Function<Double,Long> fun2 = Math::round;
System.out.println (fun2.apply ( 14.5 ) );
}
// 情况三:类 :: 实例方法
// Comparator中的int comapre(T t1,T t2)
// String中的int t1.compareTo(t2)
@Test
public void test5() {
//最原始的实现方法:使用匿名内部类的方式
Comparator<String> com = new Comparator<String> ( ) {
@Override
public int compare ( String o1 , String o2 ) {
int compare = o1.compareTo ( o2 );
return compare;
}
};
System.out.println ( com.compare ( "abc" , "abc" ) );
System.out.println ( );
//使用lambda表达式实现
Comparator<String> com1 = (o1,o2) -> o1.compareTo ( o2 );
System.out.println ( com1.compare ( "asd" , "asd" ) );
System.out.println ( );
//使用方法引用的方式实现
Comparator<String> com2 = String::compareTo;
System.out.println ( com2.compare ( "qwe" , "qwe" ) );
}
//BiPredicate中的boolean test(T t1, T t2);
//String中的boolean t1.equals(t2)
@Test
public void test6() {
//最原始的方式实现,匿名内部类
BiPredicate<String,String> bi = new BiPredicate<String, String> ( ) {
@Override
public boolean test ( String s , String s2 ) {
return s.equals ( s2 );
}
};
System.out.println ( bi.test ( "asd" , "asd" ) );
System.out.println ( );
//lambda表达式实现
BiPredicate<String,String> bi1 = (s,s1) -> s.equals ( s1 );
System.out.println ( bi1.test ( "asd" , "asd" ) );
System.out.println ( );
//方法引用实现
BiPredicate<String,String> bi2 = String::equals;
System.out.println ( bi2.test ( "qwe" , "qwe" ) );
}
// Function中的R apply(T t)
// Employee中的String getName();
@Test
public void test7() {
Employee employee = new Employee (1001,"Sam",20,14000 );
//最原始的实现方法,匿名内部类
Function<Employee, String> fun = new Function<Employee, String> ( ) {
@Override
public String apply ( Employee s ) {
return s.getName ();
}
};
System.out.println ( fun.apply ( employee ) );
System.out.println ( );
//lambda表达式实现
Function<Employee,String> fun1 = emp -> employee.getName ();
System.out.println ( fun1.apply ( employee ) );
System.out.println ( );
//方法引用实现
Function<Employee,String> fun2 = Employee::getName;
System.out.println ( fun2.apply ( employee ) );
}
}
三、构造器引用与数组引用
3.1、格式
类名::new
3.2、构造器引用的使用要求
和方法引用类似,函数式接口的形参列表和构造方法中的形参列表一致,函数式接口的返回值类型为构造方法所属的类的类型
3.3、示例
/**
* 一、构造器引用
*
* 二、数组引用
*
*
* Created by shkstart
*/
public class ConstructorRefTest {
//构造器引用
//Supplier中的T get()
@Test
public void test1(){
//匿名内部类方式实现
Supplier<Employee> su = new Supplier ( ) {
@Override
public Employee get ( ) {
return new Employee ( );
}
};
System.out.println ( su.get ( ) );
System.out.println ( );
//lambda方式实现
Supplier<Employee> su1 = () -> new Employee ( );
System.out.println ( su1.get ( ) );
System.out.println ( );
//构造器引用实现
Supplier<Employee> su2 = Employee::new;
System.out.println ( su2.get ( ) );
}
//Function中的R apply(T t)
@Test
public void test2(){
//匿名内部类方式实现
Function<Integer,Employee> fun = new Function<Integer, Employee> ( ) {
@Override
public Employee apply ( Integer integer ) {
return new Employee ( integer);
}
};
System.out.println ( fun.apply ( 1001 ) );
System.out.println ( );
//lambda方式实现
Function<Integer,Employee> fun1 = id -> new Employee ( id );
System.out.println ( fun1.apply ( 1002 ) );
System.out.println ( );
//构造器引用实现
Function<Integer,Employee> fun2 = Employee::new;
System.out.println ( fun2.apply ( 1003 ) );
}
//BiFunction中的R apply(T t,U u)
@Test
public void test3(){
//匿名内部类方式实现
BiFunction<Integer,String,Employee> bif = new BiFunction<Integer, String, Employee> ( ) {
@Override
public Employee apply ( Integer integer , String s ) {
return new Employee ( integer,s );
}
};
System.out.println ( bif.apply ( 1004 , "KING" ) );
System.out.println ( );
//lambda方式实现
BiFunction<Integer,String,Employee> bif1 = (id,name) -> new Employee ( id,name );
System.out.println ( bif1.apply ( 1005 , "TOM" ) );
System.out.println ( );
//构造器引用实现
BiFunction<Integer,String,Employee> bif2 = Employee::new;
System.out.println ( bif2.apply ( 1006 , "Jeery" ) );
}
//数组引用
//Function中的R apply(T t)
@Test
public void test4(){
//匿名内部类方式实现
Function<Integer, String[]> fun = new Function<Integer, String[]> ( ) {
@Override
public String[] apply ( Integer length ) {
return new String[ length ];
}
};
String[] strings = fun.apply ( 5 );
System.out.println ( Arrays.toString ( strings ) );
System.out.println ( );
//lambda方式实现
Function<Integer,String[]> fun1 = length -> new String[length];
String[] strings1 = fun1.apply ( 10 );
System.out.println ( Arrays.toString ( strings1 ) );
System.out.println ( );
//构造器引用实现
Function<Integer,String[]> fun2 = String[]::new;
String[] strings2 = fun2.apply ( 15 );
System.out.println ( Arrays.toString ( strings2 ) );
}
}