Lambda的使用方法

197 阅读5分钟

体验lambda表达式

@Test
public void lambdaTest01(){
    // 老的写法
   Runnable runnable = new Runnable() {
       @Override
       public void run() {
           System.out.println("Run 方法执行了");
       }
   };
   runnable.run();
   // 新的写法
   Runnable runnable1 = ()->System.out.println("lambda run");
   runnable1.run();
}

lambda 在写法上更加的间接,写的代码行数更少

lambda的语法格式:(形参1,形参2...形参n) -> 重写抽象方法的方法体

无参数,无返回值

@Test
public void lambdaTest02(){
    Runnable runnable = () -> { System.out.println("runnable run"); };
    runnable.run();
    Runnable runnable1 = ()-> System.out.println("runnable run");
    runnable1.run();
}

有参数,没有返回值

image.png

@Test
public void lambdaTest03(){
    Consumer consumer = (monry) -> System.out.println("肯德基的价格是:"+monry);
    consumer.accept(100);
    Consumer consumer1 = (money) -> { System.out.println("汉堡的价格是:" + money); };
    consumer1.accept(100);
    Consumer consumer2 = (mv) -> { System.out.println("我爱看:" + mv); };
    consumer2.accept("四驱兄弟");
}

有一个参数,小括号可以省略

@Test
public void lambdaTest04(){
    Consumer consumer1 = money ->  System.out.println("汉堡的价格是:" + money);
    consumer1.accept(100);
}

有参数,有返回值

@Test
public void lambdaTest05(){
    Comparator<Integer> comparator = (o1, o2) -> {return o1.compareTo(o2);};
    int compare = comparator.compare(25, 20);
    System.out.println(compare);

    Comparator<Integer> comparator1 = (o1,o2) -> o1.compareTo(o2);
    int compare1 = comparator1.compare(25, 20);
    System.out.println(compare1);
}

认识函数式接口

一个接口里只有一个抽象方法,并且在这个抽象方法上标注FunctionalInterface注解的。

image.png

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

image.png

演示案例

@Test
public void lambdaTest06(){
    //Consumer
    Consumer consumer = (name -> {
        System.out.println("我叫:" + name);
    });
    consumer.accept("牛某某");
    //Supplier
    Supplier supplier = () -> {return "You are Smart";};
    Object o = supplier.get();
    System.out.println(o);
    //Function
    Function<Integer,Double> function = (num1) -> {return Double.valueOf(num1); };
    Double apply = function.apply(10);
    System.out.println(apply);
    //Predicate
    Predicate<Integer> predicate = (number) -> {return  number >= 20;};
    boolean test = predicate.test(20);
    System.out.println(test);
}

运行结果:

image.png

方法引用

实例::对象方法

Consumer 中的 void accept(T t)

PrintStream 中的 void println(T t)

@Test
public void lambdaTest07(){
    Consumer<String> con1 = s -> System.out.println(s);
    con1.accept("上海");
    System.out.println("******************");
    PrintStream ps = System.out;
    Consumer<String> con2 = ps::println;
    con2.accept("北京");
}
@Test
public void lambdaTest08(){
    // Supplier    T get();
    // Employee    int getAge()
    Employee employee = new Employee();
    employee.setAge(18);
    Supplier<Integer> supplier = employee::getAge;
    Integer age = supplier.get();
    System.out.println(age);
    //Consumer  void accept(T t);
    //Employee  void setSalary(double salary)
    Consumer<Double> consumer = employee::setSalary;
    consumer.accept(100.00);
    System.out.println(employee.getSalary());
}

类::静态方法

@Test
public void lambdaTest09(){
    //lambda表达式的写法
    Comparator<Integer> com = (t1,t2) -> Integer.compare(t1,t2);
    System.out.println(com.compare(12, 21));

    //方法引用的写法
    Comparator<Integer> com1 = Integer::compare;
    System.out.println(com1.compare(10, 20));
}

类::非静态方法

@Test
public void lambdaTest10(){
    Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
    System.out.println(com1.compare("abc", "def"));
    //Comparator   int compare(T o1, T o2);
    //String中的    int o1.compareTo(o2)
    Comparator<String> com2 = String::compareTo;
    System.out.println(com2.compare("abc", "def"));
}

构造器引用

@Test
public void lambda11(){
    //Supplier T get();
    //Employee Employee() 
    System.out.println();
    //lambda表达式写法
    Supplier<Employee> sup = ()->new Employee();
    System.out.println(sup.get());
    //构造器引用的写法
    Supplier<Employee> sup1 = Employee :: new;
    System.out.println(sup1.get());
}

数组引用

@Test
public void lambda11(){
    //lambda 表达式
    Function<Integer,String[]> func1 = length -> new String[length];
    String[] apply = func1.apply(5);
    System.out.println(Arrays.toString(apply));
    System.out.println("******************************************");
    //数组引用的写法
    Function<Integer,String[]> func2 = String[] :: new;
    String[] apply1 = func2.apply(10);
    System.out.println(Arrays.toString(apply1));
}

StreamAPI

Stream 的三个操作步骤

1- 创建 Stream

​ 一个数据源(如:集合、数组),获取一个流

2- 中间操作

​ 一个中间操作链,对数据源的数据进行处理

3- 终止操作(终端操作)

​ 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用

image.png

Stream 实例化

package com.java.entity;

/**
 * 其他的方法 请自行生成
 */
public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;
}

/**
 * 提供用于测试的数据
 * 
 * @author shkstart 邮箱:shkstart@126.com
 *
 */
public class EmployeeData {
    
    public static List<Employee> getEmployees(){
        List<Employee> list = new ArrayList<>();
        list.add(new Employee(1001, "马化腾", 34, 6000.38));
        list.add(new Employee(1002, "马云", 12, 9876.12));
        list.add(new Employee(1003, "刘强东", 33, 3000.82));
        list.add(new Employee(1004, "雷军", 26, 7657.37));
        list.add(new Employee(1005, "李彦宏", 65, 5555.32));
        list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));
        list.add(new Employee(1007, "任正非", 26, 4333.32));
        list.add(new Employee(1008, "扎克伯格", 35, 2500.32));
        list.add(new Employee(1003, "刘强东", 33, 3000.82));
        return list;
    }    
}

实例化方式一:通过集合

// default Stream<E> stream() : 返回一个顺序流
// default Stream<E> parallelStream() : 返回一个并行流
List<Employee> employees = EmployeeData.getEmployees();
//返回一个顺序流
Stream<Employee> stream = employees.stream();
//返回一个并行流
Stream<Employee> parallelStream = employees.parallelStream();

实例化方式二:通过数组

//static <T> Stream<T> stream(T[] array): 返回一个流    
@Test
    public void streamTest1(){
        int[] arr = new int[]{1,2,3,4,5,6};
        IntStream stream = Arrays.stream(arr);

        Employee e1 = new Employee(1001, "Tom");
        Employee e2 = new Employee(1002, "lucy");

        Employee[] arr1 = {e1, e2};
        Stream<Employee> stream1 = Arrays.stream(arr1);
    }

实例化方式三:通过Stream.of

// public static<T> Stream<T> of(T... values) : 返回一个流
@Test
public void streamTest2(){
  Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
}

创建无限流

//迭代
//public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) 
//生成
//public static<T> Stream<T> generate(Supplier<T> s) 
@Test
public void streamTest3(){
//遍历前10个数
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
//生成10个数
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}

Stream的中间操作

筛选与切片

   @Test
    public void streamTest4(){
        List<Employee> list = EmployeeData.getEmployees();
        //filter
        Stream<Employee> stream = list.stream();
        stream.filter(e -> e.getSalary()>7000).forEach(System.out::println);
        System.out.println();
        //limit
        list.stream().limit(3).forEach(System.out::println);
        System.out.println();
        //skip
        list.stream().skip(4).forEach(System.out::println);
        System.out.println();
        //distinct
        list.stream().distinct().forEach(System.out::println);
    }

映射

    @Test
    public void streamTest5(){
        //map
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

        //小练习:获取员工姓名长度大于3的员工的姓名
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<String> nameStream = employees.stream().map(Employee::getName);
        nameStream.filter(name -> name.length()>3).forEach(System.out::println);

        Stream<Stream<Character>> streamStream = list.stream().map(jdk8Test2Stream::fromStringStream);
        streamStream.forEach(s -> {
            s.forEach(System.out::println);
        });
        System.out.println("****************************************************************");
        //flagMap
        Stream<Character> characterStream = list.stream().flatMap(jdk8Test2Stream::fromStringStream);
        characterStream.forEach(System.out::println);
    }

    public static Stream<Character> fromStringStream(String str){
        ArrayList<Character> list = new ArrayList<>();
        for (Character c:str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }
map(Function f)接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream。
flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流
方法描述
filter(Predicate p)接收 Lambda , 从流中排除某些元素
distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize)截断流,使其元素不超过给定数量
skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一 个空流。与 limit(n) 互补

排序

    @Test
    public void streamTest6(){
         //sorted 自然排序
        List<Integer> list = Arrays.asList(12, 34, 65, 34, 877, 0, -98, 7);
        list.stream().sorted().forEach(System.out::println);
        //sorted(Comparator com) 定制排序
        List<Employee> employees = EmployeeData.getEmployees();
        employees.stream().sorted((e1,e2) ->                                              Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println);
    }

Stream的终止操作

匹配和查找

方法描述
allMatch(Predicate p)检查是否匹配所有元素
anyMatch(Predicate p)检查是否至少匹配一个元素
noneMatch(Predicate p)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回当前流中的任意元素
count()返回流中元素总数
max(Comparator c)返回流中最大值
min(Comparator c)返回流中最小值
forEach(Consumer c)内部迭代(使用 Collection 接口需要用户去做迭代, 称为外部迭代。相反,Stream API 使用内部迭 代——它帮你把迭代做了)
    @Test
    public void streamTest7(){
        List<Employee> employees = EmployeeData.getEmployees();

        //allMatch
        boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
        System.out.println(allMatch);

        //anyMatch
        boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);
        System.out.println(anyMatch);

        //noneMatch
        boolean noneMatch = employees.stream().noneMatch(e -> e.getName().contains("雷"));
        System.out.println(noneMatch);

        //findFirst
        Optional<Employee> findFirst = employees.stream().findFirst();
        System.out.println(findFirst);
        
        //findAny
        Optional<Employee> findAny = employees.stream().findAny();
        System.out.println(findAny);

        //count
        long count = employees.stream().count();
        System.out.println(count);

        //max
        Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
        Optional<Double> max = salaryStream.max(Double::compareTo);
        System.out.println(max);

        //min
        Optional<Employee> employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(employee);

        //forEach
        employees.stream().forEach(System.out::println);
    }

规约

方法描述
reduce(T iden, BinaryOperator b)可以将流中元素反复结合起来,得到一 个值。返回 T
reduce(BinaryOperator b)可以将流中元素反复结合起来,得到一 个值。返回 Optional
    @Test
    public void streamTest8(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        //reduce
        Integer sum = list.stream().reduce(0, Integer::sum);
        System.out.println(sum);
        //reduce(BinaryOperator b)
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Double> doubleStream = employees.stream().map(Employee::getSalary);
        Optional<Double> reduce = doubleStream.reduce((d1, d2) -> d1 + d2);
        System.out.println(reduce);
        //Optional<Double> sumMoney = doubleStream.reduce(Double::max);
        //System.out.println(sumMoney);
    }

收集

方法规约
collect(Collector c)将流转换为其他形式。接收一个 Collector 接口的实现,用于给Stream中元素做汇总 的方法

image.png

image.png

    @Test
    public void streamTest9(){
        List<Employee> employees = EmployeeData.getEmployees();
        List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
        employeeList.forEach(System.out::println);
        System.out.println();
        Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
        employeeSet.forEach(System.out::println);
    }

Optional类

Optional类的相关方法

image.png

Option类的使用

创建两个新的实体类

public class Boy {
    private Girl girl;
    public Boy() {}
    public Boy(Girl girl) {
        this.girl = girl;
    }
    public Girl getGirl() {
        return girl;
    }
    public void setGirl(Girl girl) {
        this.girl = girl;
    }

    @Override
    public String toString() {
        return "Boy{" +
                "girl=" + girl +
                '}';
    }
}
public class Girl {
    private String name;
    public Girl(String name) {
        this.name = name;
    }
    public Girl() {}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Girl{" +
                "name='" + name + ''' +
                '}';
    }
}
    @Test
    public void optionTest1(){
        Girl girl = new Girl();
        Optional<Girl> girl1 = Optional.of(girl);
        System.out.println(girl1);
    }

    @Test
    public void optionalTest2(){
        Girl girl = new Girl();
        girl = null;
        Optional<Girl> girl1 = Optional.ofNullable(girl);
        System.out.println(girl1);
    }

    @Test
    public void optionalTest3(){
        Optional<Object> empty = Optional.empty();
        System.out.println(empty);
    }

Optional类的使用举例

//如何有效避免空指针
    @Test
    public void optionalTest4(){
        Girl girl = new Girl();
        girl = null;
        Optional<Girl> optionalGirl = Optional.ofNullable(girl);
        System.out.println(optionalGirl);
        System.out.println("***************************");
        /**
         * orElse(T t)
         *   如果optional内部封装的T是非空的,则返回内部的t
         *   如果optional内部封装的T是空的,则返回orElse()方法中的参数
         */
        Girl otherGirl = optionalGirl.orElse(new Girl("嗯哼"));
        System.out.println(otherGirl);
    }