详解Java8中的函数式接口

本文详细介绍了Java中的函数式接口,包括概念、格式及@FunctionalInterface注解的使用。同时,深入探讨了常用函数式接口如Supplier、Consumer、Predicate、Function的应用场景与实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数式接口

概念 

函数式接口是指:有且只有一个抽象方法的接口。

函数式接口,即适用于函数式编程场景的接口,而Java中的函数式编程体现的就是Lambad,所以函数式接口就是适用于Lambda适用的接口,只要确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利进行推导。

函数式接口格式

修饰符 interface 接口名称{
    public abstract 返回值类型 方法名称(参数信息);
}

public interface MyFunctionInterace{
    public abstract void method();
}

@FunctionalInterface 注解

Java8 中专门为 函数式接口引入了一个全新的注解:@FunctionalInterface,该注解用于在一个接口的定义上

@FunctionalInterface
public interface MyFunctionInterace{
    public abstract void method();
}

一旦适用该注解来标记接口,编译器会强制检查该接口是否有且只有一个抽象方法,否则就会编译报错

常用的函数式接口 

Supplier:生产者

java.util.function.Supplier<T> 接口被称为生产型接口,指定接口中的泛型是什么类型,那么接口中的 抽象方法就会生产什么类型

抽象方法:get

@FunctionalInterface
public interface Supplier<T> {

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

使用:求数组中的最大值

public class Demo02Test {
    public static void main(String[] args) {
        int[] arr = {100, 0, -50, 88, 99, 33, -30};

        //调用getMax方法,方法的参数Supplier是一个函数式接口,所以可以 传递Lambda表达式
        int arrMax = getMax(() -> {
            //获取数组的最大值,并返回
            //定义一个变量,把数组中的第一个元素赋值给该变量,记录数组中的最大值
            int max = arr[0];
            for (int i : arr) {
                //使用其他元素和最大值比较
                if (max < i)
                    //如果i 大于max ,则替换max作为最大值
                    max = i;
            }
            return max;
        });
        System.out.println(arrMax);
    }

    //定义一个方法,用于获取int类型数组中的最大值,方法的参数传递Supplier接口,泛型使用Integer
    public static int getMax(Supplier<Integer> sup) {
        return sup.get();
    }
}

Consumer:消费者

java.util.function.Consumer<T> 接口则正好与Supplier接口相反,它不是生成一个数据,而是消费一个数据,其数据类型由泛型决定

抽象方法:accept

Consumer 接着中包含的抽象方法 accept ,意为消费一个指定执行泛型的数据

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

//基本使用
public class Demo09Consumer {
    private static void consumeString(Consumer<String> function) {
      	function.accept("Hello");
    }

    public static void main(String[] args) {
        consumeString(s -> System.out.println(s));
    }
}

默认方法:andThen

如果一个方法的参数和返回值都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作,然后再做一个操作,实现组合。那那么就可以使用默认方法 andThen

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}

提示:java.util.ObjectsrequireNonNull静态方法将会在参数为null时主动抛出NullPointerException异常。

使用:先输出字符串的大写,再输出字符串的小写

public class Demo10ConsumerAndThen {
    private static void consumeString(Consumer<String> one, Consumer<String> two) {
    	//con1.adnThen(con2); 谁写前边谁先消费
      	one.andThen(two).accept("Hello");
    }

    public static void main(String[] args) {
        consumeString(
            s -> System.out.println(s.toUpperCase()),
            s -> System.out.println(s.toLowerCase()));
    }
}
//这样写看起来很高大上,但是感觉很鸡肋,其实完全可以写在一起,先大写再小写

Predicate:判断者

需要对某种类型的数据进行判断,得到一个boolean值结果。这时可以使用java.util.function.Predicate<T>接口

抽象方法:test

Predicate接口中包含一个抽象方法:boolean test(T t)。用于条件判断的场景:

public class DemoPredicate {
    /*
    boolean test(T t):用来对指定数据类型数据进行判断的方法
    定义一个方法 对字符串长度进行判断,大于5返回true
     */
    public static boolean checkString(String s, Predicate<String> p) {
        return p.test(s);
    }

    public static void main(String[] args) {
        //定义一个字符串
        String s = "abcdef";
        boolean b = checkString(s, ele -> ele.length() > 5);
        System.out.println(b);
    }
}

默认方法:and

既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个Predicate条件使用“与”逻辑连接起来实现“并且”的效果时,可以使用default方法and。其JDK源码为:

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

如果要判断一个字符串的长度既要大于5,又要包含小写“a”: 

public class DemoPreicate_and {
    public static void main(String[] args) {
        String str = "abcde";
        boolean a = checkString(str, ele -> ele.length() > 5, ele -> ele.contains("a"));
        System.out.println(a);
    }

    public static boolean checkString(String s, Predicate<String> p1, Predicate<String> p2) {
        return p1.and(p2).test(s);
    }
}

默认方法:or

and的“与”类似,默认方法or实现逻辑关系中的“”。JDK源码为:

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

如果要判断一个字符串的长度大于5或者包含小写“a”

public class DemoPredicate_or {
    public static void main(String[] args) {
        String str = "bcdef1";
        boolean b = checkString(str, ele -> ele.length() > 5, ele -> ele.contains("a"));
        System.out.println(b);
    }

    public static boolean checkString(String s, Predicate<String> p1, Predicate<String> p2) {
        return p1.or(p2).test(s);
    }
}

默认方法:negate

negate方法就是对boolean值进行取反,真为假,假为真 ,其JDK源码为:

default Predicate<T> negate() {
    return (t) -> !test(t);
}

使用:

/**
 * 判断一个字符串的长度是否大于5
 * 如果字符串的长度大于5,那么返回false
 * 如果字符串的长度不大于5,那么返回true
 */
public class DemoPredicate_negate {
    public static void main(String[] args) {
        String str = "abc";

        boolean b = checkString(str, ele -> ele.length() > 5);
        System.out.println(b);
    }

    public static boolean checkString(String s, Predicate<String> p1) {
        return p1.negate().test(s);
    }
}

Function:转换者

java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。

抽象方法:apply

Function接口中最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。

使用的场景例如:将String类型转换为Integer类型。

public class Demo01Function {
    public static void change(String s, Function<String, Integer> fun) {
        int in = fun.apply(s); //自动拆箱
        System.out.println(in);

    }


    public static void main(String[] args) {
        String s = "1234";
        change(s, ele -> Integer.parseInt(ele));
    }
}

如果需要了解Lambda的使用,请查看我的另一篇博客:Java8新特性 :Lambda表达式一

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值