JDK新语法 之 Lambda表达式

最近JDK13都出来了,所以想沉下心来,总结一下JDK的一系列新语法。这个模块将抽空慢慢填充完整。

这一章就先写下Lambda表达式吧。下面我会以代码的形式进行表达

一、Lambda表达式语法

/**
 * 一、函数式接口:即接口类中只有一个方法,如compareInterface
 * 二、lambda表达式的基础语法:引入了一个新的操作符 "->"
 *     箭头左侧: 参数列表--即函数式接口方法中的参数列表
 *     箭头右侧: 执行方法--即函数式接口方法中的实现方法
 *
 * 三、语法格式:
 *    1、  无参函数--无返回值
 *         ()->System.out.println("Hello Lambda");
 *    2、  一个参数--无返回值
 *         (e)->System.out.println("hello Lambda2");
 *         或
 *         e->System.out.println("hello Lambda2");
 *    3、  两个参数--一个返回值,一条语句
 *         (e1,e2)-> return e1-e2;
 *         或
 *         (e1,e2)-> e1-e2; //return 和 {} 都可以省略不写
 *
 *         两个参数--一个返回值,多条语句
 *         (e1,e2)->{
 *             System.out.println("hello Lambda");
 *             return e1-e2;
 *         }
 *
 *   注意:lambda表达式的参数列表可以  不写  参数类型,JVM会根据上下文进行推断
 *
 */

1、先来认识一下Lambda

package com.lee.jdk.lambda;

import org.junit.Test;

import java.util.Arrays;
import java.util.Comparator;

public class TestLamda {

    //原来的匿名内部类
    @Test
    public void test01(){

        Integer[] arr = {2,7,1,5,3};
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        });
        for (int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
    }

    //lambda
    @Test
    public void test02(){
        Integer[] arr = {2,7,1,5,3};

        Arrays.sort(arr,(o1,o2)->Integer.compare(o1,o2));

        for (int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
    }
}

2、Lambda的语法规则和认知

Employee实体,下面会用到

package com.lee.jdk.Entity;

public class Employee {

    private Integer id;

    private String name;

    private int age;

    private Double salary;

    public Employee() {
    }

    public Employee(Integer id) {
        this.id = id;
    }

    public Employee(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Employee(Integer id, String name, int age, Double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

CompareInterface接口下面也会用到

package com.lee.jdk.Entity;

public interface CompareInterface<T> {

    Boolean myCompare(T t);

}

CompareImpl接口实现

package com.lee.jdk.Entity;

public class CompareImpl implements CompareInterface<Employee> {

    @Override
    public Boolean myCompare(Employee employee) {
        return employee.getAge()>35;
    }
}

Lambda的语法规则:

package com.lee.jdk.lambda;

import com.lee.jdk.Entity.CompareImpl;
import com.lee.jdk.Entity.CompareInterface;
import com.lee.jdk.Entity.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;

/**
 * 一、函数式接口:即接口类中只有一个方法,如compareInterface
 * 二、lambda表达式的基础语法:引入了一个新的操作符 "->"
 *     箭头左侧: 参数列表--即函数式接口方法中的参数列表
 *     箭头右侧: 执行方法--即函数式接口方法中的实现方法
 *
 * 三、语法格式:
 *    1、  无参函数--无返回值
 *         ()->System.out.println("Hello Lambda");
 *    2、  一个参数--无返回值
 *         (e)->System.out.println("hello Lambda2");
 *         或
 *         e->System.out.println("hello Lambda2");
 *    3、  两个参数--一个返回值,一条语句
 *         (e1,e2)-> return e1-e2;
 *         或
 *         (e1,e2)-> e1-e2; //return 和 {} 都可以省略不写
 *
 *         两个参数--一个返回值,多条语句
 *         (e1,e2)->{
 *             System.out.println("hello Lambda");
 *             return e1-e2;
 *         }
 *
 *   注意:lambda表达式的参数列表可以  不写  参数类型,JVM会根据上下文进行推断
 *
 */
public class TestLambda2 {

    List<Employee> employeeList = Arrays.asList(
            new Employee(1,"张三",25,17000d),
            new Employee(2,"李四",18,19000d),
            new Employee(3,"王五",55,7000d),
            new Employee(4,"赵六",39,12000d),
            new Employee(5,"刘七",28,14000d)
    );

    public List<Employee> filterEmployee(List<Employee> employeeList, CompareInterface<Employee> ci){
        List<Employee> resList = new ArrayList<>();
        for (Employee emp: employeeList) {
            if(ci.myCompare(emp)){
                resList.add(emp);
            }
        }
        return resList;
    }

    //1、匿名内部类
    @Test
    public void test1(){
        //年龄>35
        List<Employee> employees = filterEmployee(employeeList, new CompareImpl());
        for (Employee emp: employees) {
            System.out.println(emp);
        }

        System.out.println("------------------------");

        List<Employee> employees2 = filterEmployee(employeeList, new CompareInterface<Employee>() {
            @Override
            public Boolean myCompare(Employee employee) {
                return employee.getAge()>35;
            }
        });

        for (Employee emp: employees2) {
            System.out.println(emp);
        }

    }


    //2、lambda表达式简写匿名内部类
    @Test
    public void test2(){
        //年龄>35
        List<Employee> employees = filterEmployee(employeeList,(e)-> e.getAge()>35);
        for (Employee emp: employees) {
            System.out.println(emp);
        }
    }

    //3、语法格式一:()-> 无返回值
    @Test
    public void test3(){
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world");
            }
        };
        r1.run();

        System.out.println("-------------");

        Runnable r2 = ()-> System.out.println("hello lambda");
        r2.run();
    }

    //4、语法格式二:(e)-> 无返回值
    @Test
    public void test4(){
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("hello world--->"+s);
            }
        };
        consumer.accept("你好世界!");

        System.out.println("------------------------------");
        Consumer consumer1 = (e)-> System.out.println("hello Lambda--->"+e);
        consumer1.accept("你好Lambda!");
    }

    //5、语法格式三:(e1,e2)->一个返回值,一条或多条语句
    @Test
    public void test5(){

        Comparator<Integer> comp = (x,y)->x-y;
        System.out.println(comp.compare(12, 3));

        System.out.println("===================");

        Comparator<Integer> comp1 = (x,y)->{
            System.out.println("hello lambda");
            return x-y;
        };
        System.out.println(comp1.compare(12, 3));

    }

}

3、JDK8内置的4大核心函数,以及其Lambda的表达

package com.lee.jdk.lambda;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * JAVA8 内置4大核心函数式接口
 *
 * 1、Consumer<T> 消费性接口
 *      void accept(T t)
 *
 * 2、Supplier<T> 供给型接口
 *      T get()
 *
 * 3、Function<T,R> 函数型接口
 *      R apply(T t)
 *
 * 4、Predicate<T>  断言型接口: 判断操作
 *      boolean tesst<T t>
 */
public class TestLambda3 {

    //1、消费式接口:Consumer<T>
    @Test
    public void test1(){
        happy(10000,(m)-> System.out.println("刚哥喜欢大宝剑,每次消费"+m+"元"));
    }

    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }

    //2、供给型接口:Supplier<T>
    @Test
    public void test2(){
        List<Integer> numberList = getNumberList(10, () -> (int) (Math.random() * 100));
        for (Integer i : numberList) {
            System.out.println(i);
        }
    }

    public List<Integer> getNumberList(int num, Supplier<Integer> sup){
        List<Integer> resList = new ArrayList<>();
        for(int i=0;i<num;i++){
            Integer number = sup.get();
            resList.add(number);
        }
        return resList;
    }

    //3、函数型接口:Function<T,R>
    @Test
    public void test3(){
        String res = stringHandler("hello lambda", (s) -> s.toUpperCase());
        System.out.println(res);
    }

    public String stringHandler(String str, Function<String,String> func){
        return func.apply(str);
    }

    //4、断言型接口:Predicate<T>
    @Test
    public void test4(){
        List<String> paramsLists = Arrays.asList("hello","world","lee","ren","home","haha");
        List<String> list = filterStr(paramsLists, (s) -> s.length() < 5);
        for (String s : list){
            System.out.println(s);
        }
    }

    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> resList = new ArrayList<>();
        for (String s : list){
            if(pre.test(s)){
                resList.add(s);
            }
        }
        return resList;
    }
}

二、Lambda方法引用

package com.lee.jdk.lambda;

import com.lee.jdk.Entity.Employee;
import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 方法引用:若lambda体中的内容有方法已实现了,我们可以使用方法引用。
 *
 * [注意:引用的方法 要和实现的方法  的  参数列表  和  返回值  一致]
 *
 * 主要有三种语法格式:
 *      对象::实例方法名
 *
 *      类::静态方法名
 *
 *      类::实例方法名(第一个参数是方法的调用者,第二个参数是方法的参数时 用这种语法格式如 a.equals(b))
 */
public class TestMethodRef {

    //1.1、对象::实例方法名
    @Test
    public void test1(){
        Consumer con = (x)-> System.out.println(x);
        con.accept("abcdef");

        System.out.println("===========================");

        //System.out.println方法已经被实现了
        PrintStream ps1 = System.out;
        Consumer con1 = (x)->ps1.println(x);
        con1.accept("123456");

        System.out.println("===========================");

        //System.out.println方法已经被实现了
        PrintStream ps2 = System.out;
        Consumer con2 = ps2::println;//或Consumer con2 = System.out::println;
        con1.accept("a1b2c3d4e5f6");
    }

    //1.2、对象::实例方法名
    @Test
    public void test2(){
        Employee emp = new Employee(1,"lee",25,19999d);

        Supplier<String> sup1 = ()-> emp.getName();
        System.out.println(sup1.get());;

        System.out.println("============================");

        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());;

        System.out.println("============================");

        Supplier<Integer> sup3 = emp::getAge;
        System.out.println(sup3.get());;
    }

    //1.3、类::静态方法名
    @Test
    public void test3(){
        Comparator<Integer> comp1 = (x,y)->Integer.compare(x,y);
        System.out.println(comp1.compare(10,12));

        System.out.println("============================");
        Comparator<Integer> comp2 = Integer::compare;
        System.out.println(comp1.compare(10,12));
    }

    //1.4、类::实例方法名(第一个参数是方法的调用者,第二个参数是方法的参数时 用这种语法格式如 a.equals(b))
    @Test
    public void test4(){
        BiPredicate<String,String> biPre1 = (x,y)->x.equals(y);
        System.out.println(biPre1.test("abc","123"));

        System.out.println("============================");

        BiPredicate<String,String> biPre2 = String::equals;
        System.out.println(biPre2.test("abc","abc"));
    }

}

三、Lambda构造器引用

package com.lee.jdk.lambda;

import com.lee.jdk.Entity.Employee;
import org.junit.Test;

import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 构造器引用
 *
 * [注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致 ]
 *
 *  语法格式:
 *      ClassName::new
 */
public class TestConstructorRef {

    //数组引用: String[]::new

    //1、构造器引用  无参
    @Test
    public void test1(){
        Supplier<Employee> sup1 = ()->new Employee();
        System.out.println(sup1.get());

        System.out.println("=======================");
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());
    }

    //2、构造器引用  1个参数 或  多个参数
    @Test
    public void test2(){
        Function<Integer,Employee> func = (x)->new Employee(x);
        System.out.println(func.apply(1));

        System.out.println("========================");
        Function<Integer,Employee> func2 = Employee::new;
        System.out.println(func2.apply(2));

        System.out.println("========================");
        BiFunction<Integer,String,Employee> biFunc = Employee::new; //(x,y)->new Employee(x,y);
        System.out.println(biFunc.apply(3,"ren"));
    }
}

### 回答1: Lambda 表达式是 Java 8 中引入的一种的编程方式,它允许您简洁地编写匿名函数。它的语法如下: (参数列表) -> {函数体} 例如: (int x, int y) -> x + y 这是一个接受两个 int 类型参数并返回一个 int 类型结果的 Lambda 表达式。它等价于以下匿名内部类: new BinaryOperator<Integer>() { @Override public Integer apply(int x, int y) { return x + y; } } Lambda 表达式可以被用作方法的参数或返回值。它们可以简化使用匿名内部类的代码,使代码更简洁,更易于阅读和维护。 常见用法: - 使用 Lambda 表达式替代匿名内部类 - 使用 Lambda 表达式作为参数传递给方法 - 使用 Lambda 表达式作为返回值返回 使用 Lambda 表达式需要注意几点: - Lambda 表达式只能用于函数式接口(functional interface)的实例。函数式接口是只有一个抽象方法的接口。 - 参数类型可以省略,编译器会自动推断出来。 - 如果函数体只有一条语句,则花括号和 return 关键字都可以省略。 希望这能帮助您快速理解 Lambda 表达式。 ### 回答2: 要快速理解JDK 8中的Lambda表达式,可以按照以下步骤进行: 1. 了解Lambda表达式的基本语法Lambda表达式由参数列表、箭头符号和函数体组成。例如:(参数列表) -> 函数体。 2. 理解Lambda表达式的作用:Lambda表达式是一种简洁的语法,可用于替代匿名内部类来实现函数式接口。 3. 学习函数式接口的概念:函数式接口是只有一个抽象方法的接口。Lambda表达式可以与函数式接口相匹配,从而创建接口的实例。 4. 熟悉Lambda表达式的常用操作:Lambda表达式可以用于对集合进行遍历、过滤、映射等操作,以及作为方法参数和返回值。 5. 练习Lambda表达式的使用:通过编写一些简单的Lambda表达式示例代码,来熟悉Lambda表达式的使用方式。 6. 查阅官方文档和教程:阅读JDK 8中关于Lambda表达式的官方文档和在线教程,详细了解Lambda表达式的具体用法和特性。 7. 参考示例代码和实战经验:学习其他人使用Lambda表达式的示例代码和实战经验,可以从中获取对Lambda表达式的更深入理解。 总之,要快速理解JDK 8中的Lambda表达式,除了学习其语法和用法外,还需要与函数式接口概念相结合,并结合实际应用场景进行练习和实践。 ### 回答3: 要快速理解JDK 8中的Lambda表达式,可以按照以下步骤进行: 1. 了解Lambda表达式的概念:Lambda表达式是一种匿名函数,它可以作为参数传递给方法或保存到变量中。Lambda表达式可以简化代码,使代码更加紧凑和易读。 2. 学习Lambda表达式语法Lambda表达式语法由参数列表、箭头符号和代码块组成。例如,(参数列表) -> {代码块}。 3. 掌握Lambda表达式的基本用法:可以使用Lambda表达式替代匿名内部类的写法,例如在集合的迭代中使用Lambda表达式来简化代码。 4. 熟悉Lambda表达式的常见函数式接口:JDK 8引入了函数式接口,它们与Lambda表达式紧密相关。常见的函数式接口包括Consumer、Supplier、Predicate、Function等,可以通过Lambda表达式直接实现这些接口中的抽象方法。 5. 学习Lambda表达式的变量捕获机制:Lambda表达式可以捕获外部方法的局部变量,但是被捕获的变量必须是final或实际上是final的。 6. 实践Lambda表达式的应用场景:尝试在自己的代码中使用Lambda表达式,例如使用Lambda表达式来实现排序、过滤、映射等操作,以及在多线程编程中应用Lambda表达式。 通过以上步骤,可以快速理解和应用JDK 8中的Lambda表达式。在实践中不断尝试,深入理解Lambda表达式的特性和优势,从而更好地利用Lambda表达式提升代码的简洁性和可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值