JDK8新特性–函数式接口

JDK8新特性–函数式接口

前言—回顾lambda表达式

要说明白什么是函数式接口,就要回到我们之前学习到的lambda表达式了,我们都知道,我们要使用lambda表达式的话,需要一个接口,而且该接口内只能有一个抽象方法,比如说下面这个例子:

package com.features.functionInterface;

public class originalMethod {
    public static void main(String[] args) {
        Sum(a->{
            int sum = 0;
            for (int i : a) {
                sum+=i;
            }
            return sum;
        });
    }

    public static void Sum(Test test){
        int[] a ={1,2,3,4,5,6,7,8,9};
        int sum = test.getSum(a);
        System.out.println("sum="+sum);
    }

}
// 函数式接口
@FunctionalInterface
interface Test{
    int getSum(int[] arr);
}
复制代码

这时候,我们就会发现一个问题:我们每次需要使用lambda表达式的时候,都需要函数式接口和抽象方法,就很麻烦。而lambda表达式在使用时不关心接口名,抽象方法名,只关心抽象方法的参数列表和返回值类型。

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

函数式接口详解

函数式接口的种类

位置在lib包下lib\rt.jar!\java\util\function,在这里可以看到JDK提供给我们的函数式接口

image.png

在这里我就挑选几个比较常用的函数式接口来进行讲解,其他如果还有兴趣的,可以自己去翻阅源码。

Supplier

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
复制代码
  1. 无参有返回值 用来生产数据
  2. 案例实现:找出数组中的最大值
package com.features.functionInterface;

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

// 使用JDK8定义的函数式接口Supplier
// Supplier:无参有返回值   用来生产数据
public class SupplierTest {
    public static void main(String[] args) {
        getMax(()->{
            int[] a={1,2,5,3,6,4,8,9,7};
            Arrays.sort(a);
            return a[a.length-1];
        });
    }
    public static void getMax(Supplier<Integer> supplier){
        Integer max = supplier.get();
        System.out.println("Max:"+max);
    }
}

复制代码

结果:

image.png

Consumer

@FunctionalInterface
public interface Consumer<T> {

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

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
复制代码
  1. 有参无返回值 用来消费数据
  2. andThen 默认方法 用来组合方法实现
  3. 案例实现:字符串大小写转换
package com.features.functionInterface;

import java.util.function.Consumer;

// Consumer: 有参无返回值  用来消费数据
public class ConsumerTest {
    public static void main(String[] args) {
        change(message -> System.out.println(message + "转换为小写后,变成" + message.toLowerCase()));
        changeAndThen(msg1 -> System.out.println(msg1 + "转换为小写后,变成" + msg1.toLowerCase()),
                msg2 -> System.out.println(msg2 + "转换为大写后,变成" + msg2.toUpperCase()));
    }

    public static void change(Consumer<String> consumer) {
        consumer.accept("Hello,Consumer");//转换为小写
    }

    public static void changeAndThen(Consumer<String> c1, Consumer<String> c2) {
        String str = "Hello,World";
        // 第一种写法,分别调用
        //c1.accept(str); // 转换为小写
        //c2.accept(str); // 转换为大写
        // 第二种用法  先执行c1,再执行c2
        //c1.andThen(c2).accept(str);
        // 第二种用法  先执行c2,再执行c1
        c2.andThen(c1).accept(str);
    }
}

复制代码

结果:

image.png

Function

  1. 有参有返回值:根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
  2. andThen 默认方法,组合实现
  3. compose 默认方法,组合实现,和andThen效果相反
  4. 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);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
复制代码
  1. 案例实现:字符串和数字的转换
package com.features.functionInterface;

import java.util.function.Function;

// Function: 有参有返回值 根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
public class FunctionTest {
    public static void main(String[] args) {
        //test1(msg-> Integer.parseInt(msg));
        // 也可以替换为
        test1(Integer::parseInt);
        // andThen
        test2(msg1-> {
            int i = Integer.parseInt(msg1);
            System.out.println("字符串转为数字,结果为:"+i);
            return i;
        }, msg2->{
            String s = String.valueOf(msg2);
            System.out.println("数字转为字符串,结果为:"+s);
            return s;
        });

        test3(msg1-> {
            int i = Integer.parseInt(msg1);
            System.out.println("字符串转为数字,结果为:"+i);
            return i;
        }, msg2->{
            String s = String.valueOf(msg2);
            System.out.println("数字转为字符串,结果为:"+s);
            return s;
        });
    }
    public static void test1(Function<String,Integer> function){
        String str = "123";
        Integer apply = function.apply(str);//字符串转换为数字
        System.out.println("字符串转为数字,结果为:"+apply);
    }

    public static void test2(Function<String,Integer> f1,Function<Integer,String> f2){
        String str = "456";
        //Integer i = f1.apply(str);//字符串转为数字
        //f2.apply(i);// 数字转为字符串
        f1.andThen(f2).apply(str);
    }

    public static void test3(Function<String,Integer> f1,Function<Integer,String> f2){
        Integer i = 789;
        //String s = f1.apply(str);//数字转为字符串
        //f2.apply(s);// 字符串转为数字
        f1.compose(f2).apply(i);
    }

}

复制代码

Predicate

  1. 有参有返回值,返回值为boolean类型
  2. and 默认方法 a&&b a,b全对才对
  3. or 默认方法 a||b a,b有一个对就对
  4. negate 默认方法 !a a对就错,a错就对
  5. isEqual 静态方法
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
复制代码
  1. 案例实现:字符串的操作
package com.features.functionInterface;

import java.util.function.Predicate;

// Predicate : 有参有返回值,返回值为boolean类型
public class PredicateTest {
    public static void main(String[] args) {
        test(msg -> msg.length() > 3, "hello");

        test2(msg1 -> msg1.contains("h"), msg2 -> msg2.contains("r"));
    }

    public static void test(Predicate<String> predicate, String str) {
        boolean test = predicate.test(str);
        System.out.println("字符串的长度大于3?" + test);
    }

    public static void test2(Predicate<String> p1, Predicate<String> p2) {
        //boolean b1 = p1.test("h"); // b1中是否有h
        //boolean b2 = p2.test("r");// b2中是否有r
        boolean flag1 = p1.and(p2).test("hello");// p1 && p2
        boolean flag2 = p1.or(p2).test("hello"); // p1 || p2
        boolean flag3 = p1.negate().test("hello"); // !p1
        System.out.println("hello中是否同时存在h和r:"+flag1);
        System.out.println("hello中是否有h和r的任意一个:"+flag2);
        System.out.println("hello中不包含h:"+flag3);
    }
}

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享