06. 函数式接口Consumer\Supplier\Function\Predicate

28 阅读3分钟

06. 函数式接口 Consumer\Supplier\Function\Predicate

package com.lambda.fun;

/**
 * @Author:kaiyang.cui
 * @Package:com.lambda.fun
 * @Project:jdk8
 * @name:Demo01Fun
 * @Date:2023/4/2 下午8:33
 * @Filename:Demo01Fun
 * @Description:填写功能描述
 * @Version:1.0
 */
public class Demo01Fun {

    public static void main(String[] args) {
        fun1((arr)->{
            int sum = 0;

            for (int i : arr) {
                sum += i;
            }
            return sum;
        });
    }
    public static void fun1(Operator operator){
        int[] arr = {1,2,3,4,5};
        int sum = operator.getSum(arr);
        System.out.println("sum = " + sum);
    }
}


@FunctionalInterface
interface Operator{
    int getSum(int[] arr);
}

函数式接口的由来

我们知道使用lambda表达式的前提是需要有函数式接口,而lambda表达式使用时不关心接口名,抽象方法名,只关心抽象方法的参数列表和返回值类型。

因此为了让我们使用lambda表达式更加的方便,在JDK中提供了大量常用的函数式接口。

函数式接口的常用接口

函数式接口介绍

在JDK中帮我们提供函数式接口,主要在java.util.function

Consumer

有参无返回值的接口 【消费数据才会无返回值】

使用的时候需要指定泛型来定义参数类型。

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

public static void fun2(Consumer<String> consumer){
    consumer.accept("HELLO WORLD");
}


@Test
@DisplayName("Consumer 函数式接口的使用")
public void test2(){
    fun2((str)->{
        System.out.println(str + "->转换为小写" + str.toLowerCase());
    });
}

【默认方法】andThen

 public static void fun3(Consumer<String> c1, Consumer<String> c2) {
        String str = "Hello World";
//        c1.accept(str); // 转小写
//        c2.accept(str); // 转大写
        c1.andThen(c2).accept(str); // 先转小写再转大写
        c2.andThen(c1).accept(str); // 先转大写再转小写
    }
@Test
@DisplayName("Consumer 函数式接口的使用")
public void test3(){
    fun3((str)->{
        System.out.println(str + "->转为小写" + str.toLowerCase());
    },(str)->{
        System.out.println(str + "->转为大写" + str.toUpperCase());
    });
}

【案例】:将输入的数据统一转换为小写

Supplier

无参有返回值的接口【生产数据才会有返回值】

相应的lambda:对应的lambda表达式需要提供一个返回数据的类型。

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

为什么要使用下面的方式去找出一个数组中的最大值呢? 因为我们要使用lambda表达式,我们没有必要自己去声明一个接口!!!! 用java.util.function自带的就可以啦!!!!

package com.lzh;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;


import java.util.Arrays;
import java.util.function.Supplier;

/**
 * @Author:kaiyang.cui
 * @Package:com.lzh
 * @Project:jdk8
 * @name:MyTest
 * @Date:2023/4/2 下午9:07
 * @Filename:MyTest
 * @Description:MyTest
 * @Version:1.0
 */
@Slf4j
public class MyTest {


    public static void fun1(Supplier<Integer> supplier){
        Integer max = supplier.get();
        System.out.println("最大值"+ max);
    }

    @Test
    @DisplayName("Supplier 函数式接口的使用")
    public void test1(){
        fun1(()->{
            int arr[] = {22,33,44,23,4,5};
            Arrays.sort(arr);
            return arr[arr.length-1];
        });
    }
}

Function

有参且有返回值的接口

【Function接口】:根据一个类型的数据得到另一个类型的数据。

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

【案例】:传递进去一个字符串返回一个数字

public static void fun4(Function<String, Integer> function){
    Integer apply = function.apply("666");
    System.out.println("apply = " + apply);
}
@Test
@DisplayName("Function 函数式接口的使用")
public void test4() {
    fun4(msg ->{
        return Integer.parseInt(msg);
    });
}

【默认方法】:andThen,也是用来组合操作。

public static void fun5(Function<String, Integer> f1,Function<Integer, Integer> f2){
//        Integer i1 = f1.apply("666");
//        Integer i2 = f2.apply(i1);

        Integer apply = f1.andThen(f2).apply("666");
        System.out.println("i2 = " + apply);
    }
@Test
@DisplayName("Function 函数式接口的使用")
public void test5() {
    fun5(msg ->{
        return Integer.parseInt(msg);
    },(msg2)->{
        return msg2 * 2;
    });
}
  • 默认的compose方法的作用顺序和andThen方法刚好相反
  • 而静态方法identity,则是输入什么参数就返回什么结果

Predicate

有参且返回值为Boolean的接口

根据我们传入的数据进行判断,给出一个boolean类型的true或false

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

【案例】:传入一个字符串判断长度

public static void fun6(Predicate<String> predicate,String msg){
    boolean b = predicate.test(msg);
    System.out.println("b = " + b);
}
@Test
@DisplayName("Predicate 函数式接口的使用")
public void test6() {
    fun6(msg ->{
        return msg.length() > 3;
    },"Hello World");
}

在Predicate中的默认方法提供了逻辑关系操作

  • and
  • or
  • negate
  • isEquals
public static void fun7(Predicate<String> p1,Predicate<String> p2){

    // p1 包含H 同时p2 包含H
    boolean b1 = p1.and(p2).test("Hello");

    // p1 包含H 或者p2包含w
    boolean b2 = p1.or(p2).test("Hello");

    //p1 不包含H
    boolean b3 = p1.negate().test("Hello");

    System.out.println(b1);
    System.out.println(b2);
    System.out.println(b3);


}
@Test
@DisplayName("Predicate 函数式接口的使用")
public void test7() {
    fun7(msg ->{
        return msg.contains("H");
    },msg2->{
        return msg2.contains("w");
    });
}

Command + option + O 搜索类:

image.png

image.png

image.png

image.png

image.png

image.png