Java Lambda表达式

官方文档https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

写的非常的详细,很赞:https://www.cnblogs.com/haixiang/p/11029639.html

1.为什么要用Lambda表达式?

虽然匿名类的实现也很简单,但是对于只有一个方法的类,匿名类就会比较的繁琐。Lambda表达式就可以更加简洁地表达单方法类的实例。同时Lambda表达式还允许将功能作为参数,将代码作为数据进行传递。

2.Lambda表达式语法

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

  1. 用逗号分隔的、括在圆括号中的形式参数列表。
  2. 箭头标志->
  3. 语句体,由单个表达式或语句块组成

注1:如果只有一个参数,可以省略圆括号

p -> p.getGender() == Person.Sex.MALE 
    && p.getAge() >= 18
    && p.getAge() <= 25

注2:如果指定单个表达式,Java运行时计算表达式并返回其值。也可以使用return语句

p -> {
    return p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25;
}

 

 

3.接受不同形式的参数的Lambda表达式例子

import java.util.function.BinaryOperator;
import java.util.function.Consumer;

public class Lambda3 {
    public static void main(String[] args) {

        //无参无返回
        Runnable r1 = () -> System.out.println("hello lambda!");

        //一个参数无返回
        Consumer<String> fun1 = (arg) -> System.out.println(arg);
        //只有一个参数时,圆括号可以省略
        Consumer<String> fun2 = arg -> System.out.println(arg);

        //多个参数无返回
        BinaryOperator<Long> bo1 = (Long x, Long y) -> {
            System.out.println("实现函数式接口!");
        };
        //数据类型可以省略
        BinaryOperator<Long> bo2 = (x, y) -> {
            System.out.println("实现函数式接口!");
        };

        //当Lambda只有一条语句时,return和{}可以省略
        BinaryOperator<Long> bo3 = (x, y) -> x + y;

    }
}

实例一:

实体类

import lombok.Data;

@Data
public class Employee {
    private String name;
    private Integer age;
    private double salary;

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

最繁琐的实现方式:每一个需求都得写一个实现方法,有大量重复的代码

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Lambda4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77)
    );

    // 年龄大于20的员工
    public List<Employee> filterEmployee1(List<Employee> list) {
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : list) {
            if (emp.getAge() > 20) {
                emps.add(emp);
            }
        }
        return emps;
    }

    // 薪资大于3000的员工
    public List<Employee> filterEmployee2(List<Employee> list) {
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : list) {
            if (emp.getSalary() > 3000) {
                emps.add(emp);
            }
        }
        return emps;
    }

    @Test
    public void test(){
        List<Employee> emps1 = filterEmployee1(employees);
        for(Employee emp:emps1){
            System.out.println(emp);
        }
        System.out.println("-------------------------------------------");
        List<Employee> emps2 = filterEmployee2(employees);
        for(Employee emp:emps2){
            System.out.println(emp);
        }
    }

}

优化方式一:策略设计模式(又是一个要填的坑...)

首先写一个接口myPredicate.java

public interface myPredicate<T> {
    public boolean filter(T t);
}

再写一个类实现这个接口中的抽象方法FilterEmployeeByAge .java

public class FilterEmployeeByAge implements myPredicate<Employee>{
    @Override
    public boolean filter(Employee t){
        return t.getAge()>20;
    }
}

然后在主方法中调用

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Lambda4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77)
    );

    // 这次只用写一个方法就可以重复调用不同的条件,按照年龄或者按照薪资等
    public List<Employee> filterEmployeeOpt1(List<Employee> list, myPredicate<Employee> mp) {
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : list) {
            if (mp.filter(emp)) {
                emps.add(emp);
            }
        }
        return emps;
    }

    @Test
    public void test1() {
        List<Employee> emps1 = filterEmployeeOpt1(employees, new FilterEmployeeByAge());
        for (Employee emp : emps1) {
            System.out.println(emp);
        }
        System.out.println("-------------------------------------------");
        List<Employee> emps2 = filterEmployeeOpt1(employees, new FilterEmployeeBySalary());
        for (Employee emp : emps2) {
            System.out.println(emp);
        }
    }

}

如果想要新增其他过滤条件,就新建类来重写之前的接口方法FilterEmployeeBySalary.java

public class FilterEmployeeBySalary implements myPredicate<Employee>{
    @Override
    public boolean filter(Employee t){
        return t.getSalary()>3000;
    }
}

优化方式二:匿名内部类 匿名内部类

不需要每次有新需求的时候,都新建一个文件。但是实际有用的代码只有一行,代码比较冗余

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Lambda4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77)
    );

    // 这次只用写一个方法就可以重复调用不同的条件,按照年龄或者按照薪资等
    public List<Employee> filterEmployeeOpt(List<Employee> list, myPredicate<Employee> mp) {
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : list) {
            if (mp.filter(emp)) {
                emps.add(emp);
            }
        }
        return emps;
    }

    @Test
    public void test2() {
        List<Employee> emps = filterEmployeeOpt(employees, new myPredicate<Employee>() {
            @Override
            public boolean filter(Employee t) {
                return t.getAge() > 20; //有效代码
            }
        });
        for (Employee emp : emps) {
            System.out.println(emp);
        }
    }

}

优化方式三:Lambda表达式

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Lambda4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77)
    );

    // 这次只用写一个方法就可以重复调用不同的条件,按照年龄或者按照薪资等
    public List<Employee> filterEmployeeOpt(List<Employee> list, myPredicate<Employee> mp) {
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : list) {
            if (mp.filter(emp)) {
                emps.add(emp);
            }
        }
        return emps;
    }

    @Test
    public void test3() {
        List<Employee> emps = filterEmployeeOpt(employees, (e) -> e.getAge() > 20); //lambda表达式只写最主要的代码
        emps.forEach(System.out::println);
    }
}

优化方式四:Stream API(又是一个后面要填的坑...)

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Lambda4 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 1111.33),
            new Employee("李四", 19, 2222.44),
            new Employee("王五", 20, 3333.55),
            new Employee("赵六", 21, 4444.66),
            new Employee("田七", 22, 5555.77)
    );

    @Test
    public void test4() {
        employees.stream()
                .filter((e) -> e.getAge() > 20)
                .forEach(System.out::println);
    }
}

这太NB,好简洁,并且有多种功能。。。

4.函数式接口

只包含一个抽象方法的接口

实例二:

public class Lambda2 {

    @FunctionalInterface  // 只包含一个抽象方法的接口,函数式接口
    interface IntegerMath {
        int operation(int a, int b);
    }

    // 定义一个方法
    public int operateBinary(int a, int b, IntegerMath op) {
        return op.operation(a, b);
    }

    public static void main(String... args) {

        Lambda2 myApp = new Lambda2();
        // Lambda表达式实现数据运算
        IntegerMath addition = (a, b) -> a + b;
        IntegerMath subtraction = (a, b) -> a - b;
        System.out.println("40 + 2 = " +
                myApp.operateBinary(40, 2, addition));
        System.out.println("20 - 10 = " +
                myApp.operateBinary(20, 10, subtraction));
    }
}

Java内置四大核心函数式接口

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;

// 四大核心接口
public class Lambda6 {
    @Test
    public void test1(){
        List<Integer> list = getNumList(10,()->(int)(Math.random()*100));
        for (Integer num:list){
            System.out.println(num);
        }
    }
    public List<Integer> getNumList(int num,Supplier<Integer> sup){
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<num;i++){
            Integer n =sup.get();
            list.add(n);
        }
        return list;
    }

    @Test
    public void test2(){
        play(100000,(m)-> System.out.println("renz:"+m));
    }

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

    @Test
    public void test3(){
        String UPStr=strHandle("aaa",(str)->str.toUpperCase());
        System.out.println(UPStr);
    }

    public String strHandle(String str,Function<String,String> fun){
        return fun.apply(str);
    }

    @Test
    public void test4(){
        List<String> strlist= Arrays.asList("aaaa","bbbb","cccc","ddd");
        List<String> newList=filterStr(strlist,(str)->str.length()>3);
        for (String str:newList){
            System.out.println(str);
        }
    }

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

核心函数式接口,提供了非常抽象分方法,按照需要可以直接使用

方法引用与构造器引用

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.Function;
import java.util.function.Supplier;

/**
 * Lambda体中调用方法的参数列表与返回值,要与函数式接口中的抽象方法的函数列表和返回值类型保持一致
 * Lambda参数列表中的第一参数时实例方法的调用者,而第二参数是实例方法的参数时,可以用ClassName::method
 */
public class Lambda7 {
    // 方法引用
    @Test
    public void test1() {
        Consumer<String> con1 = (s) -> System.out.println(s);
        con1.accept("雅俗共赏");

        // 对象::实例方法
        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        Consumer<String> con3 = System.out::println;
        con2.accept("长歌行");
        con3.accept("长歌行");
    }

    @Test
    public void test2() {
        Employee emp=new Employee("张三", 18, 1111.33);
        Supplier<String> sup1=()->emp.getName();
        String strName = sup1.get();
        System.out.println(strName);
        //对象:实例方法
        Supplier<Integer> sup2=emp::getAge;
        Integer age=sup2.get();
        System.out.println(age);
    }

    @Test
    public void test3() {
        Comparator<Integer> com1 = (x, y) -> Integer.compare(x, y);
        System.out.println(com1.compare(1, 2));

        //类::静态方法名
        Comparator<Integer> com2 = Integer::compare;
        System.out.println(com2.compare(2, 2));
    }

    @Test
    public void test4() {

        BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
        System.out.println(bp1.test("aa", "bb"));
        // 类::实例方法名
        BiPredicate<String, String> bp2 = String::equals;
        System.out.println(bp2.test("aa", "aa"));
    }

    //构造器引用 ClassName::new
    //需要调用的构造器的参数列表要与函数式接口中的抽象方法的参数列表保持一致
    @Test
    public void test5() {
        Supplier<Employee> sup1 = () -> new Employee("张三", 18, 1111.33);
        Employee emp1 = sup1.get();

        //构造器引用方式
        Supplier<Employee> sup2 = Employee::new;
        Employee emp2 = sup2.get();
        System.out.println(emp1);
        System.out.println(emp2);

        Function<Integer,Employee> fun=Employee::new;
        Employee emp3=fun.apply(12);
        System.out.println(emp3);
    }

    //数组引用
    @Test
    public void test6(){
        Function<Integer,String[]> fun1 = (x)->new String[x];
        String[] str1= fun1.apply(2);
        System.out.println(str1.length);

        Function<Integer,String[]> fun2 = String[]::new;
        String[] str2=fun2.apply(3);
        System.out.println(str2.length);
    }
}

细品~~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值