Java8新特性之Lambda表达式

简介

lambda是用来实现接口的一个匿名函数。

( ):用来描述参数列表

{ }:用来描述方法体

-> : lambda运算法,读作goes to

垃圾代码 --> 策略模式 --> 匿名内部类 --> Lambda表达式

接口准备

无参数无返回值

@FunctionalInterface
public interface LambdaNoneReturnNoneParameter {
    void test();
}

单个参数无返回值

@FunctionalInterface
public interface LambdaNoneReturnSingleParameter {
    void test(int n);
}

多个参无返回值

@FunctionalInterface
public interface LambdaNoneReturnManyParameter {
    void test(int n,int b);
}

无参数有返回值

@FunctionalInterface
public interface LambdaSingleReturnNoneParameter {
    int test();
}

单个参数有返回值

@FunctionalInterface
public interface LambdaSingleReturnSingleParameter {
    int test(int n);
}

多个参数有返回值

@FunctionalInterface
public interface LambdaSingleReturnManyParameter {
    int test(int a,int b);
}

基本语法

lambda是实现接口的匿名函数

lambada语法

public class Syntax1 {
    public static void main(String[] args) {
        //lambda是实现接口的匿名函数
        //参数列表 方法体
        //无参无返回
        //@FunctionalInterface标识接口 只有一个方法
        LambdaNoneReturnNoneParameter lambda1 = ()->{
            System.out.println("hello world");
        };
        lambda1.test();
        //无返回值,单个参数
        LambdaNoneReturnSingleParameter lambda2 = (int a)->{
            System.out.println(a);
        };
        lambda2.test(2);
        //无返回值,多个参数
        LambdaNoneReturnManyParameter lambda3 = (int a, int b)->{
            System.out.println(a+" "+b);
        };
        lambda3.test(1,2);

        //有返回值,无参
        LambdaSingleReturnNoneParameter lambda4 = ()->{
            System.out.println("lambda4");
            return 100;
        };
        int ret = lambda4.test();
        System.out.println(ret);
        //有返回值,单个参数
        LambdaSingleReturnSingleParameter lambada5 = (int a)->{
            System.out.println("lambda5");
            return a;
        };
        int ret2 = lambada5.test(5);
        System.out.println(ret2);
        LambdaSingleReturnManyParameter lambda6 = (int a,int b)->{
            System.out.println("lambda6");
            return a+b;
        };
        int ret3 = lambda6.test(1,2); 
    }
}

精简语法

public class Syntax2 {
    //语法精简
    //1. 参数类型
    // 要么都省略掉,要么不省略
    LambdaNoneReturnManyParameter lambda1 = (a, b)->{
        System.out.println("lambda1");
    };
    //2. 参数列表
    // 参数的类型只有一个,此时小括号可以省略
    LambdaNoneReturnSingleParameter lambda2 = a ->{
        System.out.println("lambda2");
    };
    //3. 大括号省略
    // 方法体中只有一条语句时
    LambdaNoneReturnSingleParameter lambda3 = a -> System.out.println("lambda3");
    //4. 如果方法体中的唯一语句时返回语句,可以省略return
    LambdaSingleReturnNoneParameter lambda4 = () -> 10;
    LambdaSingleReturnSingleParameter lambda5 = a -> a;
    LambdaSingleReturnManyParameter lambda6 = (a,b)-> a+b;

}

方法引用

public class Syntax3 {
    public static void main(String[] args) {
        // 方法引用
        // 可以快速的将一个lambda表达式的实现指向一个已经实现的方法。
        // 语法:方法的隶属者::方法名
        // 注意:
        // 1. 静态方法       类名::方法名
        // 2. 非静态方法:   对象名:方法名  

        //注意:
        //1. 参数数量和类型一定要和接口中定义的方法一致
        //2. 返回值得类型和接口中定义方法一致
        LambdaSingleReturnSingleParameter lambda1 = a -> change(a);

        //方法引用:引用了change方法的实现。
        LambdaSingleReturnSingleParameter lambda2 = Syntax3::change; 
    }
    public static int change(int a){
        return a*2;
    }
}

构造方法引用

public class Syntax4 {
    public static void main(String[] args) {
        PersonCreater creater1 = ()-> new Person();
        //构造方法的引用
        PersonCreater creater2 =Person::new;
        Person person = creater2.getPerson();
        System.out.println(person);
        //有参的
        PersonCreater2 creater3 = Person::new;
        Person person3 = creater3.getPerson2("Jack",18);
        System.out.println(person3);
    }

    // 需求:
    interface PersonCreater{
            Person getPerson();
    }
    interface PersonCreater2{
            Person getPerson2(String name,int age);
    }
}

Person

public class Person {
    public String name;
    public int age;

    public Person() {
        System.out.println("无参构造方法");
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造方法");
    }

    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;
    }

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

集合排序

ArrayList 排序

import java.util.ArrayList;

public class exercise1 {
    public static void main(String[] args) {
        //集合排序
        //ArrayList<>
        //需求:一个list中有若干个person,按照年龄降序排序
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("jack",10));
        list.add(new Person("lisa",23));
        list.add(new Person("jie",23));
        list.add(new Person("dd",13));
        list.add(new Person("lun",14));
        list.add(new Person("shun",12));
        list.add(new Person("hao",15));
        list.add(new Person("zhu",16));
        //排序
        list.sort((o1,o2)->{
            return o1.age - o2.age;
        });
        //简化
        list.sort((o1,o2)-> o1.age-o2.age);
        System.out.println(list);

    }
}

TreeSet 排序

import java.util.TreeSet;

public class exercise2 {
    public static void main(String[] args) {
//        TreeSet   实现降序
//        TreeSet<Person> set = new TreeSet<>();
//        set.add(new Person("jack",10));
//        set.add(new Person("lisa",23));
//        set.add(new Person("jie",23));
//        set.add(new Person("dd",13));
//        set.add(new Person("lun",14));
//        set.add(new Person("shun",12));
//        set.add(new Person("hao",15));
//        set.add(new Person("zhu",16));
//        System.out.println(set); 抛出异常,不知道按照哪个元素排序,分不清谁大谁小
        //方法一:实现Comparable接口中的方法,自然排序。例如一个数字的集合
        //方法二:使用lambada表达式实现Comparator,定制排序。例如一个对象的集合
        TreeSet<Person> set2 = new TreeSet<>(((o1, o2) -> o1.age - o2.age));
        set2.add(new Person("lisa", 23));
        set2.add(new Person("jie", 23));
        set2.add(new Person("dd", 13));
        set2.add(new Person("lun", 14));
        set2.add(new Person("shun", 12));
        set2.add(new Person("hao", 15));
        set2.add(new Person("zhu", 16));
        System.out.println(set2);
        //出现相同年龄的只保留一个

        //可以重写排序规则
        TreeSet<Person> set3 = new TreeSet<>((o1, o2) -> {
            if (o1.age >= o2.age){
                return -1;
            }else {
                return 1;
            }
        });
        set3.add(new Person("lisa", 23));
        set3.add(new Person("jie", 23));
        set3.add(new Person("dd", 13));
        set3.add(new Person("lun", 14));
        set3.add(new Person("shun", 12));
        set3.add(new Person("hao", 15));
        set3.add(new Person("zhu", 16));
        System.out.println(set3);
    }
}

集合的遍历 forEach

import java.util.ArrayList; 
import java.util.Collections;

public class exercise3 {
    public static void main(String[] args) {
        //集合的遍历
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7,8,9);
        //将集合中的每一个元素都带入到Consumer的accept方法中
        list.forEach(System.out::println);
        //加入自己的逻辑
        list.forEach(ele ->{
            if (ele%2 == 0){
                System.out.println(ele);
            }
        });

    }
}

集合删除元素 removeif

import java.util.ArrayList;
import java.util.ListIterator;

public class exercise4 {
    public static void main(String[] args) {
        //需求:删除集合中满足条件的元素
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("jack",10));
        list.add(new Person("lisa",23));
        list.add(new Person("jie",23));
        list.add(new Person("dd",13));
        list.add(new Person("lun",14));
        list.add(new Person("shun",12));
        list.add(new Person("hao",15));
        list.add(new Person("zhu",16));
        //使用Iterator 删除集合中年两大于15的元素
        ListIterator<Person> it = list.listIterator();
        while (it.hasNext()){
            Person ele = it.next();
            if (ele.age>15){
                it.remove();
            }
        }
        System.out.println(list);

        //使用lambada表达式
        //将集合中的每一个元素都带入到Predicate的test方法中,如果返回值是true,则删除这个元素,例子中如果满足年龄大于10的元素则删除
        list.removeIf(ele ->  ele.age>10 );
        System.out.println(list);
    }
}

线程实例化

public class exercise5 {
    public static void main(String[] args) {
        //需求:开辟一个线程,输出数字,开辟一个线程可以通过继承Thread或者实现Runnable接口
        //可以使用匿名内部类或者实现Runnable接口
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        });
        t.start();
        //使用lambda,Runnable是一个无参无返回的FunctionalInterface接口
        Thread t2 = new Thread(()-> System.out.println("hello lambda"));
        t2.start();
    }
}

系统内置函数式接口

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

函数式接口 参数类型 返回类型 用途
Consumer 消费型接口 T void 对类型为T的对象应用操作:void accept(T t)
Supplier 提供型接口 T 返回类型为T的对象:T get()
Function<T, R> 函数型接口 T R 对类型为T的对象应用操作,并返回结果为R类型的对象:R apply(T t)
Predicate 断言型接口 T boolean 确定类型为T的对象是否满足某约束,并返回boolean值:boolean test(T t)
public class FunctionInterface {
    public static void main(String[] args) {
        // 系统内置函数式接口

        //Predicate<T>  :           参数T 返回boolean
        //      IntPredicate        int->boolean
        //      LongPredicate       long->boolean
        //      DoublePredicate     double->boolean

        //Consumer<T>   :           参数T 返回void
        // IntConsumer  :            int ->void
        // LongConsumer :            long -> void
        // DoubleConsumer :          double -> void

        //Function<T,R> :           参数T 返回R        指定传入参数指定返回参数类型
        //      IntFunction<R>          int -> R
        //      LongFunction<R>         long -> R
        //      DoubleFunction<R>       double -> R
        //      IntToLongFunction       int -> long
        //      IntToDoubleFunction     int -> double
        //      LongToIntFunction       long -> int
        //      LongToDoubleFunction    long -> double
        //      DoubleIntFunction       double -> int
        //      DoubleToLongFunction    double -s long

        //Supplier<T>     :         参数无 返回T
        //UnaryOperator   :         参数T,R 返回T
        //BiFunction<T,U,R> :       参数T,U 返回R
        //BiConsumer<T,U>  :        参数T,U   返回值void
    }
}

消费型接口

@Test
public void test01(){
    //Consumer
    Consumer<Integer> consumer = (x) -> System.out.println("消费型接口" + x);
    //test
    consumer.accept(100);
} 

提供型接口

@Test
public void test02(){
    List<Integer> list = new ArrayList<>();
    List<Integer> integers = Arrays.asList(1,2,3); 
    list.addAll(integers);
    //Supplier<T>
    Supplier<Integer> supplier = () -> (int)(Math.random() * 10);
    list.add(supplier.get());
    System.out.println(supplier);
    for (Integer integer : list) {
        System.out.println(integer);
    }
}

函数型接口

@Test
public void test03(){
    //Function<T, R>
    String oldStr = "abc123456xyz";
    Function<String, String> function = (s) -> s.substring(1, s.length()-1);
    //test
    System.out.println(function.apply(oldStr));
}

断言型接口

@Test
public void test04(){
    //Predicate<T>
    Integer age = 35;
    Predicate<Integer> predicate = (i) -> i >= 35;
    if (predicate.test(age)){
        System.out.println("你该退休了");
    } else {
        System.out.println("我觉得还OK啦");
    }
}

闭包问题

public class ClosureDemo {
    public static void main(String[] args) {
        int n = getNumber().get(); //get方法是Supplier接口
        //闭包 提高变量的生命周期。getNumber方法结束时,变量应该销毁,但是输出了n。实现了Supplier方法,提高变量的生命周期
        System.out.println(n);
    }
    private static Supplier<Integer> getNumber(){

        int num = 100;
        //闭包
        return () -> {
            return num;
        }; 
    }
}
public class ClosureDemo2 {
    public static void main(String[] args) {
        int a = 100;    // 在编译时,会为int加上final, 从变量成为常量
        Consumer<Integer> c = ele ->{
            System.out.println(ele);
        };
        c.accept(a);

        Consumer<Integer> c2 = ele ->{
            System.out.println(a);
        };
        c2.accept(a);
        //注意:在闭包中引用的一定是常量
        // a++  则报错
        //Consumer<Integer> c2 = ele ->{
        //    System.out.println(a++);
        //};
    }
}

练习

package com.godfrey.lambda;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Arrays;
import java.util.Random;
import java.util.function.*;
import java.util.stream.Stream;

@SpringBootTest
class LambdaTest {

    @Test
    void functionInterfaceTest() {
        //1.Supplier(提供型接口):没有输入,只有输出
        Supplier<String> supplier = () -> "this is supplier demo for supplier";
        System.out.println(supplier.get());

        //2.Consumer(消费型接口):只有输入,没有输出
        Consumer<String> consumer = i -> System.out.println("this is consumer demo for " + i);
        consumer.accept("Consumer");

        //3.Function(函数型接口):输入T,输出R
        Function<Integer, Integer> function = i -> i * i;
        System.out.println("Function demo: " + function.apply(9));

        //4.Predicate(断言型接口):输入T,输出boolean
        Predicate<Integer> predicate = (i) -> i == 2;
        System.out.println(predicate.test(1));

        //5.Function实现类,输入和输出类型一致
        UnaryOperator<Integer> unaryOperator = i -> i * i;
        System.out.println("UnaryOperator demo: " + unaryOperator.apply(8));

        //6.输入T、U,输出R
        BiFunction<Integer, Integer, String> biFunction = (i, j) -> i + "*" + j + "=" + i * j;
        System.out.println(biFunction.apply(8, 9));
    }

    @Test
    void streamTest() {
        String[] arr = {"react", "", "spring", "bo_le", "webflux", "spring", "bo_le"};
        //1.Arrays
        Arrays.stream(arr).forEach(System.out::println);

        //2.list
        Arrays.asList(arr).stream().forEach(System.out::println);

        //3.Stream.of
        Stream.of(arr).forEach(System.out::println);

        //4.迭代器 打印1-10元素
        Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);

        //5.generate 产生10个1-10随机数
        Stream.generate(() -> new Random().nextInt(10)).limit(10).forEach(System.out::println);
    }

    @Test
    void stream2Test() {
        String[] arr = {"react", "", "spring", "bo_le", "webflux", "spring", "bo_le"};

        //输出bole
        Stream.of(arr).filter(i -> !i.isEmpty())
                .distinct()
                .sorted()
                .limit(1)
                .map(i -> i.replace("_", ""))
                .flatMap(i -> Stream.of(i.split("")))
                .forEach(i -> System.out.println(i));
    }

}
posted @ 2021-06-15 16:35  对弈  阅读(160)  评论(0编辑  收藏  举报