Java教程

JavaSE基础day26 lambda表达式、消费型接口Consumer、供给性接口Supplierr

本文主要是介绍JavaSE基础day26 lambda表达式、消费型接口Consumer、供给性接口Supplierr,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

一、  Lambda表达式

2.1 概述

1. 本质:

   Lambda表达式是java对数学函数表达式的一种体现形式,本质是一个值,在java中主要是体现在对特殊的匿名内部类对象的一种表示,代表匿名内部类的对象

2. 使用前提:

       函数式接口:只有一个抽象方法的接口(可以有其他非抽象方法)

    可以在接口声明之上, 使用注解: @FunctionalInterface标识验证这个函数式接口

3. 好处:

       对匿名内部类对象的格式简化,大幅提升开发效率

注: Lambda表达式代表的匿名内部类的对象,在编译的时候不需要生成对应类的字节码文件,而匿名内部类在编译的时候需要编译生成对应的字节码文件,所以Lambda表达式可以提高效率

 

 

2.2 格式详解

1. 格式:

   (参数列表)  ->  {方法体}

2. 详细说明:

  (1) (参数列表): 表示要实现的接口中,抽象方法的参数

  (2) -> : 箭头运算符,或者称为Lambda运算符,用于分隔前后两部分

  (3) {方法体}: 也称为Lambda体,表示重写抽象方法的具体实现

@FunctionalInterface
public interface MyFunctionalInterface {
    public abstract void fun();
}

class Test{
    public static void main(String[] args) {
        // 1. 使用匿名内部类实现MyFunctionalInterface接口
        new MyFunctionalInterface(){
            @Override
            public void fun() {
                System.out.println("我是重写的fun,匿名内部类对象方法");
            }
        }.fun();

        // 2. 使用lambda表达式实现MyFunctionalInterface接口
        // (参数列表)->{方法体}
        MyFunctionalInterface my = ()->{ System.out.println("lambda表达式重写的fun"); };
        my.fun();
    }
}

 

2.3 特殊情况

1. 有且只有一个参数,可以省略小括号

       x -> {int result = x * x; System.out.println(x + “的平方为:” + result);}

2. Lambda体只有一句,且没有返回值,可以省略大括号

       x -> System.out.println(x * x);

3. Lambda体只有一句,且有返回值,则return和大括号可以一起省略

       (x, y) -> {return x + y;}  等价于 (x, y) -> x + y

       注意:要么一起省略,要么都不省略

@FunctionalInterface
public interface MyFunctionalInterface {
    public abstract void fun();
}

@FunctionalInterface
interface Inter2{
    public abstract void print(int n);
}

@FunctionalInterface
interface InterOther{
    public abstract boolean equal(double d, double d1);
}

class Test{
    public static void main(String[] args) {
        // 1. 使用匿名内部类实现MyFunctionalInterface接口
        new MyFunctionalInterface(){
            @Override
            public void fun() {
                System.out.println("我是重写的fun,匿名内部类对象方法");
            }
        }.fun();

        // 2. 使用lambda表达式实现MyFunctionalInterface接口
        // (参数列表)->{方法体}
        MyFunctionalInterface my = ()->{ System.out.println("lambda表达式重写的fun"); };
        my.fun();

        // 3. 使用lambda表达式实现参数列表只有一个的抽象方法
        Inter2 i2 = (x) -> {
            for(int i = 1; i <= x; i++){
                System.out.println(i);
            }
        };
        i2.print(5);
        // 特殊情况1: 如果使用lambda表达式作为一个函数式接口的实现类对象, 需要实现的唯一抽象方法
        // 参数列表只有一个参数, 那么lambda表达式的小括号可以省略

        Inter2 i3 = n -> {
            System.out.println(n);
        };
        i3.print(8);

        // 特殊情况2: 如果lambda表达式实现的抽象方法对应的方法体逻辑只有一句,并且没有返回值结果
        // 那么大括号可以省略
        Inter2 i4 = x -> System.out.println("x的值为:" + x);

        // 4. 使用lambda变道时实现参数列表有多个,有返回值抽象方法
        // 特殊情况3: 如果lambda表达式实现的抽象方法有返回值结果,并且逻辑只有一句,这一句逻辑正好对应方法
        // 的返回值, 那么return和大括号可以同时省略
        InterOther other = (x,y)->{return x == y;};
        System.out.println(other.equal(5.6,5.7));// false

        InterOther other3 = (x,y) -> x==y;
        System.out.println(other3.equal(4.1,4.1));// true
    }
}

 

二 、  函数式接口

2.1 概述

1、定义:如果在接口中,只有一个抽象方法,那么这个接口就是函数式接口,比如:jdk中熟悉的函数式接口 :Runnable

 

2、格式说明:

       使用注解来检查当前接口是否是一个函数式接口

              @FunctionalInterface

              如果不是函数式接口,则编译报错

3、理解:

(1) 函数:想表达的是一个方法的内容,由于方法不在任何类中,所以称为函数

(2) 函数式接口:其实想表达的就是一个抽象函数的声明

4、作用:

       使用函数式接口表达函数的声明;使用函数式接口的实现类对象表达函数的实现

5、使用原因:

       Java中不支持将函数作为一个数据,也就不能将这个函数进行各种传递,也就不能作为对象的成员变量存在

       只能在方法外加一层接口的声明,将来可以传递方法所在接口的实现类对象,来间接的传递方法实现内容

 

 

举例 : 客户要求定义出一个方法功能, 对两个整数进行任意操作

1) 两数求和

2) 两数求差

3) 两数乘积 * 2

4) ... 无数需求, 都需要在同一个方法中完成

 

public int useTwoInt(int x, int y, 对于x和y两数的操作思想,这个思想可以是一个抽象方法){

 

}

 

2.2 常用内置函数式接口

1、说明:

       Java8中提供了一些常用的函数式接口,在使用类似功能的时候,不需要额外定义接口,直接使用jdk中提供的即可

 

2、罗列:

       Consumer<T>:消费型接口

              void accept(T t): 需要传进进来参数,进行消费,没有返回值。【有进无出】

 

3、 Supplier<T>:供给型接口

              T get(): 不需要传递参数,返回创建一个数据的接口 【无进有出】

 

4、 Function<T, R>:函数型接口

              R apply(T t): 需要传递一个参数,把传递进来的参数进行一些操作,然后再返回一个参数【有进有出】

 

5、 Predicate<T>:断言型接口

              boolean test(T t): 需要参数,返回一个boolean类型的值【有进有出,出来的结果一定是boolean类型】

 

 

2.3 消费型接口

1、Consumer<T> : 消费型接口

2、抽象方法:void accept(T t) 消费使用掉任意的一个数据

3、作用:

       定义一个方法,这个方法需要传递进来数据,还需要传递进来处理这个数据的方式,并且还不需要返回值类型,就可以使用Consumer接口来当做数据处理方式的传递。

有了Consumer接口接口以后,不仅仅可以传递数据,还可以传递消费处理数据的方式。

 

案例 : 定义出一个方法功能, 客户预计消费500元现金, 每一个客户对于500元的消费都不同, 将客户的消费方式实现出来

1) 客户1 : 花了500元, 买了一把大宝剑

2) 客户2 : 花了500元, 买了一堆化妆品

3) 客户3 : 花了500元, 买了一双球鞋

4) .... 还有无限的客户有不同种消费方式

import java.util.function.Consumer;
public class ConsumerInterfaceUse {
    public static void main(String[] args) {
        Consumer<Double> con1 = x -> System.out.println("花了" + x + "元买了一把大宝剑");
        // 1)客户1 : 花了500元, 买了一把大宝剑
        testConsumer(500,con1);
        // 2)客户2 : 花了500元, 买了一堆化妆品
        Consumer<Double> con2 = x -> {
            if(x >= 500){
                System.out.println("消费超出了500元,无法购物");
            }else{
                System.out.println("花了" + x + "元买了一堆化妆品");
            }
        };
        testConsumer(500,con2);
    }

    /*案例 : 定义出一个方法功能, 客户预计消费500元现金, 每一个客户对于500元的消费都不同, 将客户的消费方式实现出来
    1)客户1 : 花了500元, 买了一把大宝剑
    2)客户2 : 花了500元, 买了一堆化妆品
    3)客户3 : 花了500元, 买了一双球鞋
    4).... 还有无限的客户有不同种消费方式

    参数列表分析:
    1. 参数1表示客户需要花费的预期金额
    2. 参数2需要对于double类型的参数1,消费(使用)方式,因此提供Consumer<Double> con, 就是为了传递
       accept(T t): 对于double类型数据进行消费(使用)
    */
    public static void testConsumer(double money, Consumer<Double> con){
        con.accept(money);
    }
}

 

2.4 供给型接口

1、Supplier<T>:供给型接口

2、抽象方法:T get() 提供返回任意类型数据的规则

3、作用:

       当一个方法需要去生产一些数据,并且生产数据的方式不确定,就可以在方法的形参列表位置传递一个 Supplier接口,将来让调用该方法的调用者把如何生产数据的方式传递进来。有了供给型接口之后,不仅仅可以传递生产数据的数量等信息,也可以传递生产数据的方式。

 

案例 : 定义出一个方法功能, 能给客户返回出一个ArrayList<Integer>类型容器, 容器中装几个数据由客户决定, 容器中承装的数据有什么规律, 由客户决定, 方法主要给客户返回一个符合客户要求的容器

1) 客户1 :  5个数据, 都是30-80之间的随机数

2) 客户2 :  8个数据, 1-100之间的随机偶数

3) ...

import java.util.ArrayList;
import java.util.Random;
import java.util.function.Supplier;

public class SupplierInterfaceUse {
    public static void main(String[] args) {
        // 1)客户1 :  5个数据, 都是30-80之间的随机数
        //  (0-50) + 30 -->30--80
        Supplier<Integer> sup = ()->new Random().nextInt(51) + 30;
        ArrayList<Integer> list = getArrayList(5,sup);
        System.out.println(list);

        // 2)客户2 :  8个数据, 1-100之间的随机偶数
        Supplier<Integer> sup2 = ()->{
            Random ran = new Random();
            int number = ran.nextInt(100)+1;
            while(number % 2 != 0){
                number = ran.nextInt(100)+1;
            }
            return number;
        };
        list = getArrayList(8,sup2);
        System.out.println(list);
    }

   /* 案例 : 定义出一个方法功能, 能给客户返回出一个ArrayList<Integer>类型容器,
            容器中装几个数据由客户决定, 容器中承装的数据有什么规律, 由客户决定,
            方法主要给客户返回一个符合客户要求的容器
    1)客户1 :  5个数据, 都是30-80之间的随机数
    2)客户2 :  8个数据, 1-100之间的随机偶数
    3)...

    分析参数列表:
    1. 需要客户提供目标存储的数据个数
    2. 需要客户提供容器中存储的数据对应的规则,需要Integer类型数据, 因此提供一个Supplier<Integer>,
      实际上提供的就是 Integer get()
    */
    public static ArrayList<Integer> getArrayList(int count, Supplier<Integer> sup){
        ArrayList<Integer> list = new ArrayList<>();
        if(count > 0){// 存储数据到list集合
            for(int i = 1; i <= count; i++){
                list.add(sup.get());
            }
        }else{// 直接返回list即可
            return list;
        }
        return list;
    }
}

 

这篇关于JavaSE基础day26 lambda表达式、消费型接口Consumer、供给性接口Supplierr的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!