Lambda 表达式的核心语法 Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符。这个操作符为 “->” , 该操作符被称 为 Lambda 操作符或剪头操作符。它将 Lambda 分为 两个部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。 Lambda表达式 需要一个 函数式接口 来支持 ,什么是函数式接口 即接口中只有一个抽象方法 使用@FunctionalInterface 注解修饰 语法格式1 test1 无参无返回值 参数的小括号不能省 如果大括号内 就一条语句 大括号也可以省 语法格式2 test2 一个参数 无返回值 参数的小括号可以省略 如果方法体就一条语句 大括号也可以省略 语法格式3 test3 两个以上参数 有返回值 参数的小括号不能省略 如果方法体就一条语句 大括号也可以省略 Lambda 表达式的参数列表的 参数类型 可以省略
/**
* @author GuoShuo
* @date 2022/6/27 19:33
*/
public class Lambdademo1 {
@Test
public void test1(){
//无参无返回值
Runnable r1 =() -> {} ;
Runnable r2 =() -> System.out.println("这里大括号可以省略");
Runnable r3 =() -> {System.out.println("这里大括号可以省略");};
}
@Test
public void test2(){
//有一个参 没有返回值
Consumer c = para -> System.out.println("昨晚花了"+para+"钱");
Consumer c1 = para -> {
System.out.println("今天花了"+para+"钱");
};
c.accept(200);
c1.accept(300);
}
@Test
public void test3(){
//有两个以上参数,有返回值
Comparator<Integer> con1 = (Integer num1,Integer num2) ->{return 1;};
Comparator<Integer> con2 = (num1,num2) -> {return Integer.compare(num1,num2);};//参数的类型可以省略
Comparator<Integer> con3 = (num1,num2)->Integer.compare(num1,num2) ; //省略掉了大括号和return
}
@Test
public void test4(){
Integer result = method(3,(num) ->{
return num * num;
});
}
public Integer method(Integer num,MyFunInter<Integer> inter){
return inter.getValue(num);
}
List<Student> list = Arrays.asList(
new Student(1,"zs",18,88.5),
new Student(2,"ls",14,89.5),
new Student(3,"ww",21,86.5),
new Student(4,"zl",19,98.5),
new Student(5,"tq",22,82.5),
new Student(6,"mb",21,83.5)
);
@Test
public void test5(){
// 使用断言型接口 过滤集合 得到90 分以上的学生信息
List<Student> students = method2(list, (s) -> {
return s.getScore() > 90;
});
System.out.println(students);
}
public List<Student> method2(List<Student> list, Predicate<Student> pre){
List<Student> students = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if(pre.test(list.get(i))){
students.add(list.get(i));
}
}
return students;
}
}
@FunctionalInterface
public interface MyFunInter<T> {
public T getValue(T t);
}
---------------------------------------------------------------------------------------------------------------------------------
相关练习 1. 调用Collections.sort() 方法 通过定制排序 比较Student 先按照年龄比 年龄相同再按照成绩比 升序 2. 声明函数式接口 接口中声明抽象方法 public String getValue(String str) 再定义一个方法 使用这个接口作为参数 实现 将一个字符串 转大写 并返回 实现 讲一个字符串 截取2到4 的索引位置 3. 声明一个带泛型的函数式接口 泛型类型为<T,R> T 为参数 R 为返回值 实现 计算两个Long类型的数的和
/**
* @author GuoShuo
* @date 2022/6/27 21:16
*/
public class LambdaDemo2 {
List<Student> list = Arrays.asList(
new Student(1,"zs",18,88.5),
new Student(2,"ls",14,89.5),
new Student(3,"ww",21,86.5),
new Student(4,"zl",19,98.5),
new Student(5,"tq",22,82.5),
new Student(6,"mb",21,83.5)
);
@Test
public void test1(){
Collections.sort(list,(s1,s2) ->{
if (s1.getAge()>s2.getAge()){
return 1;
}else if (s1.getAge()==s2.getAge()){
return s1.getScore().compareTo(s2.getScore());
}else {
return -1;
}
});
System.out.println(list);
}
@Test
public void test2(){
String hello = method2("hello",(s) ->{
return s.toUpperCase();//转为大写
});
String helloworld =method2("helloworld",(s) ->{
return s.substring(2,4);
});
}
public String method2(String str,MyFunInter1 myFunInter1){
return myFunInter1.getValue(str);
}
@Test
public void test3(){
Long along = method3(3L,5L,(num1,num2) ->{
return num1+num2;
});
}
public Long method3(Long num1,Long num2,MyFunInter2<Long,Long> myFunInter2){
return myFunInter2.testFun(num1,num2);
}
}
public interface MyFunInter1 {
public String getValue(String str);
}
public interface MyFunInter2<T,R> {
public R testFun(T t1,T t2);
}
--------------------------------------------------------------------------------------- 内置的函数式接口的练习 Consumer<T> 消费型接口 参数类型为T 返回值为 void Supplier<T> 供给型接口 无参有返回值 T get(); Function<T,R> 函数型接口 参数类型为T 返回值类型为R Predicate<T> 断言型接口 参数类型为T 返回值类型 boolean
/**
* @author GuoShuo
* @date 2022/6/27 21:43
*/
public class LambdaDemo3 {
@Test
public void test1(){
//消费型接口的使用
method1(200.0,(para)->{
System.out.println("花了钱"+para+"去学习Java");
});
}
public void method1(Double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
// 供给型接口
// 需求 得到n 个 1000 以内的随机数
List<Integer> list =method2(10,() ->{
return new Random().nextInt(1000);
});
System.out.println(list);
}
public List<Integer> method2(Integer n, Supplier<Integer> supplier){
List<Integer> integers =new ArrayList<>();
for (int i = 0; i < n; i++) {
Integer number = supplier.get();
integers.add(number);
}
return integers;
}
@Test
public void test3(){
//函数型接口
Student student = new Student();
student.setName("张三");
String s1 =method3(student,(s) ->{
return s.getName()+"好好学习";
});
System.out.println(s1);
}
public String method3(Student student, Function<Student,String> function){
return function.apply(student);
}
@Test
public void test4(){
List<String> list = Arrays.asList("java", "javaee", "mybatis", "springboot");
List<String> list1 =method4(list,(s) ->{
return s.length()>5;
});
System.out.println(list1);
}
public List<String> method4(List<String> list, Predicate<String> predicate){
List<String> strings = new ArrayList<>();
list.forEach((s)->{
if(predicate.test(s)){
strings.add(s);
}
});
return strings;
}
}
--------------------------------------------------------------------------------------- 方法引用 实现抽象方法的参数列表 必须 与 方法引用的参数列表 保持一致 //list.forEach((s)->{System.out.println(s);}); //方法引用的形式 list.forEach(System.out::println); 方法引用的语法格式: 对象名::实例方法名 类名::静态方法名 类名::实例方法名 什么时候使用方法引用呢? 当函数式接口的抽象方法的参数列表 与 lambda 体中的 所引用的 方法的参数列表 一致时(参数的类型 个数 顺序) 可以使用方法引用 只要参数列表一致 就可以使用方法引用
/**
* @author GuoShuo
* @date 2022/6/27 21:44
*/
public class TestMethodRef {
List<Student> list = Arrays.asList(
new Student(1,"zs",18,88.5),
new Student(2,"ls",14,89.5),
new Student(3,"ww",21,86.5),
new Student(4,"zl",19,98.5),
new Student(5,"tq",22,82.5),
new Student(6,"mb",21,83.5)
);
@Test
public void test1(){
list.forEach((s) ->{
System.out.println(s);
});
//方法引用的形式
list.forEach(System.out::println);
}
@Test
public void test2(){
//Consumer<String> consumer = (s) -> s.substring(2);
//
//Consumer<Integer> consumer2 = "hello"::substring; // 参数列表 指的是 参数的类型 顺序 个数
//
//consumer2.accept(2);
Student stu = new Student(1,"zs",18,88.8);
Consumer<String> con =(s) ->stu.myMethod1(s);
//变形为方法引用
Consumer<String> con2 = stu::setName;
}
@Test
public void test3(){
Student student = new Student(1,"zs",18,99.9);
Supplier<Integer> supplier = () -> student.getAge();
//引用形式
Supplier<Integer> supplier2 = student::getAge;
}
@Test
public void test4(){
//类名::静态方法名
Comparator<Integer> comparator = (x,y) -> {return Integer.compare(x,y);};
Comparator<Integer> comparator1 = Integer::compare;
Comparator<Integer> comparator2 = Integer::compare;
}
@Test
public void test5(){
//类名::实例方法名
Function<Student,String> function = (s) -> {return s.getName();};
Function<Student,String> function1 = Student::getName;
BiPredicate<String,String> bi = (s1,s2) -> {return s1.equals(s2);};
BiPredicate<String,String> bi2 = String::equals;
//什么情况下可以这样写?
//当第一个参数 是方法的调用者, 第二个 及 以后的参数 是方法的参数时 可以 类名::实例方法名
}
}
/**
* @author GuoShuo
* @date 2022/6/28 12:01
* 数组引用
*/
public class TestArrayRef {
@Test
public void test(){
Function<Integer,String[]> function =(length) -> new String[length];
Function<Integer,String []> function1 = String[]::new;
}
}
/**
* @author GuoShuo
* @date 2022/6/28 12:21
*
* 构造器引用
*/
public class TestConstructorRef {
@Test
public void test1(){
//构造器引用
Supplier<Student> supplier = () -> new Student();
Supplier<Student> supplier1 = Student::new;
Student student = supplier1.get();
}
@Test
public void test2(){
//构造器引用的增强练习
Consumer<Integer> consumer = (age) -> new Student(age); //调用参数为年龄的构造方法
Consumer<Integer> consumer1 = Student::new; //和Consumer的抽象方法的参数列表一致 所以可以这样写
consumer1.accept(18);
Function<Integer,Student> function =(age) -> new Student(age);
Function<Integer,Student> function1 = Student::new;
Student result =function1.apply(20);
BiFunction<String,Integer,Student> biFunction = (name,age) -> new Student(name,age);
BiFunction<String,Integer,Student> biFunction1 = Student::new;
}
}