Java8 新特性-Lambda表达式

1、Lambda表达式介绍

package com.zjw;

/**
 * Lambda表达式介绍
 * Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁,通过Lambda表达式,可以替代我们以前经常写的匿名内部类来实现接口。
 * Lambda表达式的本质是一个匿名函数。
 */
public class Lambda01
{
    public static void main(String[] args) {

        //1、通过子类创建对象
        F1 f = new F1Class();

        //2、使用匿名内部类
        F1 f2 = new F1() {
            @Override
            public int add(int a, int b) {
                return a+b;
            }
        };

        //3、使用Lambda表达式创建
        /**
         * Lambda语法
         * Lambda只有参数列表和方法体
         * (参数列表)->{方法体}
         */
        F1 f1 = (int a , int b)->{
            return a+b;
        };
        System.out.println(f1.add(1,2));

    }

}

interface F1{
    int add(int a , int b);
}

class F1Class implements F1{

    @Override
    public int add(int a, int b) {
        return a+b;
    }
}

2、Lambda表达式语法细讲

使用Lambda实现不同的接口

package com.zjw;

/**
 *Lambda表达式语法细讲
 * 我们搞一个案例,接口方法参数,无参,单个参数,两个参数,有返回值,没有返回值
 */
public class Lambda02
{
    public static void main(String[] args) {

        //无返回值 无参
        F1 f1 = ()->{
            System.out.println("f1");
        };
        f1.test();

        //无返回值 单参
        F2 f2 = (int a)->{
            System.out.println("f2="+a);
        };
        f2.test(2);

        //无返回值 多参
        F3 f3 = (int a , int b)->{
            System.out.println("f3="+(a+b));
        };
        f3.test(1,2);

        //有返回值 无参
        F4 f4 = () -> {
            return 4;
        };
        System.out.println(f4.test());

        //有返回值 单参数
        F5 f5 = (int a)->{
            return a;
        };
        System.out.println(f5.test(5));

        //有返回值 多参
        F6 f6 = (int c , int d)->{
            return c-d;
        };
        System.out.println(f6.test(7,1));


    }

    interface F1{
        void test();
    }

    interface F2{
        void test(int a);
    }

    interface F3{
        void test(int a , int b);
    }

    interface F4{
        int test();
    }

    interface F5{
        int test(int a);
    }

    interface F6{
        int test(int a , int b);
    }

}
f1
f2=2
f3=3
4
5
6

3、 Lambda表达式语法精简

package com.zjw;

/**
 * Lambda语法精简
 * 1、参数类型可以省略
 * 2、假如只有一个参数,()括号可以省略
 * 3、如果方法体只有一条语句,{}大括号可以省略
 * 4、如果方法体中唯一的语句是return语句,那省略大括号的同时return也要省略
 */
public class Lambda03
{
    public static void main(String[] args) {

        F1 f1 = ()->System.out.println("f1");
        f1.test();

        F2 f2 = a->System.out.println("f2="+a);
        f2.test(2);

        F3 f3 = (a , b)->System.out.println("f3="+(a+b));
        f3.test(1,2);

        F4 f4 = () -> 4;
        System.out.println(f4.test());

        F5 f5 = a-> a;
        System.out.println(f5.test(5));

        F6 f6 = (c , d)->c-d;
        System.out.println(f6.test(7,1));

    }

    interface F1{
        void test();
    }

    interface F2{
        void test(int a);
    }

    interface F3{
        void test(int a , int b);
    }

    interface F4{
        int test();
    }

    interface F5{
        int test(int a);
    }

    interface F6{
        int test(int a , int b);
    }

}

4、 Lambda方法引用

引用静态方法、普通方法

package com.zjw;

/**
 * 有时候多个lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护;
 * 这时候可以用方法引用实现:
 * 语法: 对象::方法
 * 假如是static方法,可以直接 类名::方法
 */
public class Lambda04
{
    public static void main(String[] args) {

        Lambda04 lambda04 = new Lambda04();
        F1 f1 = (a,b)-> testB(a,b);
//        F1 f1 = lambda04::testA;
        System.out.println(f1.test(1,2));
        F1 f2 = lambda04::testA;
        System.out.println(f2.test(2,3));

        F1 f3 = Lambda04::testB;
        System.out.println(f3.test(3,1));

    }

    public int testA(int a , int b){
        return a+b;
    }

    public static int testB(int a , int b){
        return a-b;
    }


    interface F1{
        int test(int a , int b);
    }

}

引用构造方法

package com.zjw;

public class Dog {
    private String name;
    private int age ;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Dog() {
    }

    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 "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
/**
 * 如果函数式接口的实现恰好可以通过调用一个类的构造方法实现,那么就可以使用构造方法引用;
 * 语法: 类名::new
 */
public class Lambda05
{
    public static void main(String[] args) {

        DogService dogService = Dog::new;
        Dog dog = dogService.getDog();
        System.out.println(dog);

        DogService2 dogService2 = Dog::new;
        Dog dog2 = dogService2.getDog("狗狗", 2);
        System.out.println(dog2);


    }

    interface DogService{
        Dog getDog();
    }

    interface DogService2{
        Dog getDog(String name , int age );
    }

}

5、 综合实例

package com.zjw;

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

/**
 * 综合实例
 */
public class Lambda06
{
    public static void main(String[] args) {

        List<Dog> list = new ArrayList<>();
        list.add(new Dog("aa",1));
        list.add(new Dog("aa",5));
        list.add(new Dog("aa",3));
        list.add(new Dog("aa",4));
        list.add(new Dog("aa",2));

        //lambda 排序
        list.sort((dog1,dog2)->dog2.getAge()-dog1.getAge());
        System.out.println(list);

        //lambda 遍历
        list.forEach(System.out::println);

        //删除年龄大于3的
        list.removeIf(dog -> dog.getAge()>3);
        list.forEach(System.out::println);

    }
}

6、 @FunctionalInterface注解

package com.zjw;

/**
 * @FunctionalInterface注解
 *
 * 前面我们会发现Consumer接口,Comparator接口都有@FunctionalInterface注解
 *
 * 这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。
 * 这种类型的接口也称为SAM接口,即Single Abstract Method interfaces
 *
 * 特点
 * - 接口有且仅有一个抽象方法
 * - 允许定义静态方法
 * - 运行定义默认 方法
 * - 允许java.lang.Object中的public方法
 * - 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionalInterface,那么编译器会报错
 */
public class Lambda07
{
    public static void main(String[] args) {

    }

    @FunctionalInterface
    interface TestInterface{

        //抽象方法
        public void sub();

        //java.lang.Object中的public方法
        public boolean equals(Object var);

        //默认方法
        default void defaultMethod(){}

        //静态方法
        public static void staticMethod(){}
    }

}

7、内建函数式接口

Java.util.function,提供四个核心接口
1、功能型接口(Function)

public interface Function<T,R>{public R apply(T t)}

【接收一个参数,返回一个处理结果】

2、消费型接口(Consumer)

public interface Consumer<T>{public void accept(T t)}

【只接收数据,不返回结果】

3、供给型接口(Supplier)

public interface Supplier<T>{public T get()}

【不接收数据,可以返回结果】

4、断言型接口(Predicate)

public interface Predicate<T>{public boolean test(T t)}

【进行判断操作使用】

函数式接口——接收参数并且返回一个处理结果
功能型接口
String类有一个方法:

public  boolean startsWith(String str)
package com.test;
import java.util.function.Function;
public class Test03 {
	public static void main(String[] args) {
		Function<String, Boolean> fun = "##123"::startsWith;
		System.out.println(fun.apply("#"));
	}
}

消费型接口(Consumer)

package com.test;
import java.util.function.Consumer;
class MyDemo
{
	public void print(String str)
	{
		System.out.println(str);
	}
}
public class Test03 {
	public static void main(String[] args) {
		Consumer<String> fun = System.out::println;
		fun.accept("Hello World!");;
	}
}

供给型接口

package com.test;
import java.util.function.Supplier;
public class Test03 {
	public static void main(String[] args) {
		Supplier<String> fun = "hello"::toUpperCase;
		System.out.println(fun.get());
	}
}

断言型接口

package com.zjw;

import java.util.function.Predicate;

public class Test03 {
    public static void main(String[] args) {
        Predicate<String> predicate = "hello"::startsWith;
        System.out.println(predicate.test("he"));
    }
}
posted @ 2020-09-10 10:32  雨中遐想  阅读(153)  评论(0编辑  收藏  举报