最后更新于

Java8函数式接口介绍

分类: java

Java8引入的函数式接口是函数式编程的核心特性。使用@FunctionalInterface注解标识,且只包含一个抽象方法的接口称为函数式接口。

📋 四大核心函数式接口

Java8提供了四大核心函数式接口:

接口类型方法签名描述用途
Supplier() -> T供给型接口不接受参数,返回结果
ConsumerT -> void消费型接口接受参数,无返回值
PredicateT -> boolean断定型接口接受参数,返回布尔值
Function<T,R>T -> R函数型接口接受参数,返回结果

🏭 Supplier供给型接口

接口定义

java.util.function.Supplier<T> 接口特点:

  • 方法签名T get()
  • 函数描述符() -> T
  • 特点:不接受参数,只返回数据
  • 用途:类似工厂方法,生产指定结果

image-20230421064410206

实战示例

配置文件读取

/**
 * Supplier使用示例
 * 读取外部配置文件
 *
 * @param fileName 文件名
 * @return util.Properties
 * @author gcoder
 * @date 2023-04-21
 */
 public static Properties readFile(String fileName) {
    Supplier<Properties> supplier = () ->{
        try (InputStream is = Test1.class.getClassLoader().getResourceAsStream(fileName);) {
            Properties properties = new Properties();
            properties.load(is);
            return properties;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    };
    return supplier.get();
 }

作为函数参数使用

/**
 * 作为函数参数使用
 *
 * @param supplier supplier
 * @author gcoder
 * @date 2023-04-21
 */
public void start(Supplier<String> supplier) {
    String s = supplier.get();
    System.out.println(s);
}

🍽️ Consumer消费型接口

接口定义

java.util.function.Consumer<T> 接口特点:

  • 方法签名void accept(T t)
  • 函数描述符T -> void
  • 特点:只接受一个参数,没有返回值
  • 用途:对输入参数执行某些操作

image-20230421065442006

实战示例

消费字符串

public static void main(String[] args) {
    acceptString("gcoder", s -> {
        String[] split = s.split("");
        String join = String.join("-", split);
        System.out.println("join = " + join);
    });
}

/**
 * 消费字符串
 *
 * @param str      str
 * @param consumer consumer
 * @author gcoder
 * @date 2023-04-21
 */
public static void acceptString(String str, Consumer<String> consumer) {
    consumer.accept(str);
}

连续消费字符串

public static void main(String[] args) {
    acceptString2("gcoder", s -> {
        String[] split = s.split("");
        String join = String.join("-", split);
        System.out.println("join = " + join);
    }, s -> {
        System.out.println(s + "第二次消费");
    });
}

/**
 * 消费字符串
 *
 * @param str       str
 * @param consumer1 consumer1
 * @param consumer2 consumer2
 * @author gcoder
 * @date 2023-04-21
 */
public static void acceptString2(String str, Consumer<String> consumer1, Consumer<String> consumer2) {
    consumer1.andThen(consumer2).accept(str);
}

🔍 Predicate断定型接口

简介

java.util.function.Predicate接口,是一个断定型接口,用于对指定类型的数据进行判断,从而得到一个判断结果(boolean类型的值)。

image-20230421100428546

示例
  1. boolean test(T t) ,用于条件判断

    image-20230421100641244

    public static void main(String[] args) {
        boolean test = checkStr("test", s -> s.length() == 4);
        System.out.println("test = " + test);
    }
    
    /**
     * 判断字符串
     *
     * @param str str
     * @param predicate predicate
     * @return boolean
     * @author gcoder
     * @date 2023-04-21
     */
    public static boolean checkStr(String str, Predicate<String> predicate) {
        return predicate.test(str);
    }
  2. Predicate<T> and(Predicate<? super T> other),用于将两个Prediccate进行逻辑判断

    image-20230421125731774

    public static void main(String[] args) {
        boolean test = checkStr("test", s -> s.length() == 4, s -> s.equals("qwer"));
        System.out.println("test = " + test);
    }
    
    /**
     * 多个条件判断字符串
     *
     * @param str str
     * @param p1  predicate
     * @param p2  predicate
     * @return boolean
     * @author gcoder
     * @date 2023-04-21
     */
    public static boolean checkStr(String str, Predicate<String> p1, Predicate<String> p2) {
        return p1.and(p2).test(str);
    }
  3. Predicate<T> negate(),用于取反判断

    image-20230421143508045

    public static void main(String[] args) {
        boolean test = checkStr2("test", s -> s.length() != 4);
        System.out.println("test = " + test);
    }
    
    /**
     * 取反判断字符串
     *
     * @param str str
     * @param p1  predicate
     * @return boolean
     * @author gcoder
     * @date 2023-04-21
     */
    public static boolean checkStr2(String str, Predicate<String> p1) {
        return p1.negate().test(str);
    }
  4. Predicate<T> or(Predicate<? super T> other),用于两个Predicate的逻辑”或“判断

    image-20230421145331669

    public static void main(String[] args) {
        boolean test = checkStr2("test", s -> s.length() == 4, s -> s.contains("z"));
        System.out.println("test = " + test);
    }
    
    /**
     * 多个条件判断字符串
     *
     * @param str str
     * @param p1  predicate
     * @param p2  predicate
     * @return boolean
     * @author gcoder
     * @date 2023-04-21
     */
    public static boolean checkStr2(String str, Predicate<String> p1, Predicate<String> p2) {
        return p1.or(p2).test(str);
    }

⚙️ Function函数型接口

接口定义

java.util.function.Function<T,R> 接口特点:

  • 方法签名R apply(T t)
  • 函数描述符T -> R
  • 特点:接受一个参数,返回另一个类型的结果
  • 用途:根据一个类型的数据得到另外一个类型的数据

image-20230421145837347

实战示例

  1. 抽象方法R apply(T t),根据类型T的参数获取类型R的结果

    image-20230421145933644

    public static void main(String[] args) {
        Integer integer = applyMethod("12345", Integer::parseInt);
        System.out.println("integer = " + integer);
    }
    
    /**
     * 字符串整数的转换
     *
     * @param str      str
     * @param function function
     * @return Integer
     * @author gaohuiwu
     * @date 2023-04-21
     */
    public static Integer applyMethod(String str, Function<String, Integer> function) {
        return function.apply(str);
    }
  2. <V> Function<V, R> compose(Function<? super V, ? extends T> before),获取apply的function

    image-20230421151122322

    public static void main(String[] args) {
        String s1 = applyMethod("12345", s -> s + "777", s -> s + "666");
        System.out.println("s1 = " + s1);
    }
    
    /**
     * 先执行前置函数
     *
     * @param str str
     * @param f1  function
     * @param f2  function
     * @return String
     * @author gaohuiwu
     * @date 2023-04-21
     */
    public static String applyMethod(String str, Function<String, String> f1, Function<String, String> f2) {
        return f1.compose(f2).apply(str);
    }
  3. <V> Function<T, V> andThen(Function<? super R, ? extends V> after),用来进行组合操作,即:”先做什么,再做什么“的场景

    image-20230421154110020

    public static void main(String[] args) {
        String s1 = applyMethod2("12345", s -> s + "777", s -> s + "666");
        System.out.println("s1 = " + s1);
    }
    
    /**
     * 执行后置函数
     *
     * @param str str
     * @param f1  function
     * @param f2  function
     * @return String
     * @author gaohuiwu
     * @date 2023-04-21
     */
    public static String applyMethod2(String str, Function<String, String> f1, Function<String, String> f2) {
        return f1.andThen(f2).apply(str);
    }

📚 总结

以上就是Java8四大核心函数式接口的详细介绍。在实际开发中,合理使用这些函数式接口可以:

优势特点

  • 简化代码:减少复杂的多重if判断
  • 提高可读性:代码更加简洁明了
  • 增强灵活性:函数式编程自由度高
  • 便于测试:独立的函数更容易单元测试
  • 支持链式调用:如andThencompose等方法

使用建议

💡 最佳实践

  • 优先使用方法引用(如Integer::parseInt
  • 合理使用Lambda表达式,避免过于复杂的逻辑
  • 善用函数式接口的组合方法(andorandThen等)
  • 在Stream API中大量使用这些函数式接口

函数式编程让我们的代码更加简洁优雅,提升开发效率和代码质量!🚀