JDK8新特性---函数式接口和方法引用

99 阅读3分钟

代码地址 github.com/cnmxf/JDK.g…

# 1.内置函数式接口来由来

使用Lambda表达式的前提需要有函数式接口,而Lambda使用时不关心接口名,抽象方法名,只关心抽

象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。

2.常用内置函数式接口介绍

它们主要在 java.util.function 包中。下面是最常用的几个接口。

  1. Supplier接口
@FunctionalInterface
public interface Supplier<T> {
public abstract T get();
}
  1. Consumer接口
@FunctionalInterface

public interface Consumer<T> {

public abstract void accept(T t);

}
  1. Function接口
@FunctionalInterface
public interface Function<T, R> {
public abstract R apply(T t);
}
  1. Predicate接口
@FunctionalInterface
public interface Predicate<T> {
public abstract boolean test(T t);
}
Predicate接口用于做判断,返回boolean类型的值

2.1Supplier接口

供给型接口,对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。

供给型接口,通过Supplier接口中的get方法可以得到一个值,无参有返回的接口。

使用Lambda表达式返回数组元素最大值

代码示例:

package com.itheima.demo03functionalinterface;
import java.util.Arrays;
import java.util.function.Supplier;
public class Demo02Supplier {
    // 使用Lambda表达式返回数组元素最大值
    public static void main(String[] args) {
        System.out.println("开始了");
        printMax(() -> {
            int[] arr = {11, 99, 88, 77, 22};
            Arrays.sort(arr); // 升序排序
            return arr[arr.length - 1];
        });
    }
    public static void printMax(Supplier<Integer> supplier) {
        System.out.println("aa");
        int max = supplier.get();
        System.out.println("max = " + max);
    }
}

2.2Consumer接口

这个这好和Supplier相反,不是生产一个数据,而是消费一个数据。其数据类型由泛型参数决定。

@FunctionalInterface
public interface Consumer<T> {
public abstract void accept(T t);
}

使用Lambda表达式将一个字符串转成大写和小写的字符串

Consumer消费型接口,可以拿到accept方法参数传递过来的数据进行处理, 有参无返回的接口,实例代码如下:

package com.itheima.demo03functionalinterface;
import java.util.function.Consumer;
public class Demo03Consumer {
    // 使用Lambda表达式将一个字符串转成大写的字符串
    public static void main(String[] args) {
        System.out.println("开始啦");
        printHello((String str) -> {
            System.out.println(str.toUpperCase());
        });
    }
    public static void printHello(Consumer<String> consumer) {
        System.out.println("aaa");
        consumer.accept("Hello World");
    }
}

**默认方法:**andThen

如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费一个数据的时候,首先做一个操

作,然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。

源代码如下:

image-20230122172715795

代码示例:

package com.itheima.demo03functionalinterface;


import java.util.function.Consumer;

public class Demo04ConsumerAndThen {
    // 使用Lambda表达式先将一个字符串转成小写的字符串,再转成大写
    public static void main(String[] args) {
        System.out.println("开始啦");
        printHello((str) -> {
            System.out.println(str.toLowerCase());
        }, (String str) -> {
            System.out.println(str.toUpperCase());
        });
    }

    public static void printHello(Consumer<String> c1, Consumer<String> c2) {
        System.out.println("aa");
        String str = "Hello World";

        c2.andThen(c1).accept(str);

    }
}

2.3Function接口

用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有参数有返回值

@FunctionalInterface
public interface Function<T, R> {
public abstract R apply(T t);
}

使用Lambda表达式将字符串转成数字

示例代码:

package com.itheima.demo03functionalinterface;
import java.util.function.Function;
public class Demo005Function {
    public static void main(String[] args) {
        System.out.println("第一步");
        getNumber((str)->{
            int i = Integer.parseInt(str);
           return i;
        });
    }
    //**使用Lambda表达式将字符串转成数字**
    public static void getNumber(Function<String , Integer> function){
        Integer apply = function.apply("1111");
        System.out.println(apply);
    }
}

默认方法:andThen :该方法同样用于“先做什么,再做什么”的场景,和 Consumer 中的 andThen 差不多:

package com.itheima.demo03functionalinterface;

import java.util.function.Function;

public class Demo06FunctionAndThen {
    // 使用Lambda表达式将字符串转成数字, 第二个操作将这个数字乘以5
    public static void main(String[] args) {
        getNumber((String str) -> {
            System.out.println(str);
            return Integer.parseInt(str);
        }, (Integer i) -> {
            return i * 5;
        });
    }

    public static void getNumber(Function<String, Integer> f1, Function<Integer, Integer> f2) {
        System.out.println("aa");
        // Integer num = f1.apply("6");
        // Integer num2 = f2.apply(num);
        Integer num2 = f1.andThen(f2).apply("6");
        System.out.println("num2 = " + num2);
    }
}

2.4Predicate****接口

有时候需要对数据的结果进行判断,从而得到一个boolean值结果。可以使用Predicate接口

@FunctionalInterface
public interface Predicate<T> {
public abstract boolean test(T t);
}
Predicate接口用于做判断,返回boolean类型的值

使用Lambda判断一个人名如果超过3个字就认为是很长的名字

示例代码:

package com.itheima.demo03functionalinterface;

import java.util.function.Predicate;

public class Demo07Predicate {
    // 使用Lambda判断一个人名如果超过3个字就认为是很长的名字
    public static void main(String[] args) {
        System.out.println("开始啦");
        isLongName((String name) -> {
            return name.length() > 3;
        });
    }

    public static void isLongName(Predicate<String> predicate) {
        System.out.println("aa");
        boolean isLong = predicate.test("迪丽热巴");
        System.out.println("是否是长名字: " + isLong);
    }
}

3.方法引用

image-20230123091528252

image-20230123091547130