一、函数式接口简介
有且仅有一个抽象方法的接口,通过在 类上标注@functionalInterface
注解进行检测。
该注解为可选,只要保证满足函数式接口定义的条件也照样是函数式接口,但建议都加上该注解(规范)。
示例:
| @FunctionalInterface |
| public interface MyFunctionalInterface { |
| void show(); |
| } |
二、作为方法的参数
示例:
| public class Test_01 { |
| public static void main(String[] args) { |
| |
| startRunnable(new Runnable() { |
| @Override |
| public void run() { |
| System.out.println("匿名内部类方式:" + Thread.currentThread().getName() + " 线程启动"); |
| } |
| }); |
| |
| startRunnable(() -> System.out.println("lambda方式:" + Thread.currentThread().getName() + " 线程启动")); |
| } |
| |
| |
| public static void startRunnable(Runnable r) { |
| new Thread(r).start(); |
| } |
| } |
运行:
| 匿名内部类方式:Thread-0 线程启动 |
| lambda方式:Thread-1 线程启动 |
三、作为方法的返回值
示例:按照字符串长度正序排序。
| public class Test_02 { |
| public static void main(String[] args) { |
| ArrayList<String> list1 = new ArrayList<>(); |
| list1.add("bbb"); |
| list1.add("a"); |
| list1.add("cc"); |
| System.out.println("排序前 = " + list1); |
| Collections.sort(list1); |
| System.out.println("默认排序后 = " + list1); |
| |
| ArrayList<String> list2 = new ArrayList<>(); |
| list2.add("bbb"); |
| list2.add("a"); |
| list2.add("cc"); |
| System.out.println("排序前 = " + list2); |
| Collections.sort(list2, getComparator()); |
| System.out.println("自定义排序后 = " + list2); |
| } |
| |
| |
| |
| |
| public static Comparator<String> getComparator() { |
| return (s1, s2) -> s1.length() - s2.length(); |
| } |
| |
| |
| public static Comparator<String> getComparator2() { |
| return Comparator.comparingInt(String::length); |
| } |
| |
| |
| public static Comparator<String> getComparator3() { |
| return new Comparator<String>() { |
| @Override |
| public int compare(String s1, String s2) { |
| return s1.length() - s2.length(); |
| } |
| }; |
| } |
| } |
运行
| 排序前 = [bbb, a, cc] |
| 默认排序后 = [a, bbb, cc] |
| 排序前 = [bbb, a, cc] |
| 自定义排序后 = [a, cc, bbb] |
四、常用函数式接口
Java 8 在 java.util.function
包下预定义了大量的函数式接口供我们使用,以下为四大核心函数式接口:
接口 |
描述 |
Supplier |
生产型接口,接口中泛型指定什么类型,则 get 方法就生产该类型数据。T 为出参类型,没有入参 |
Consumer |
消费型接口,消费的数据其类型由泛型指定。T 为入参类型,没有出参 |
Predicate |
断言式接口,通常用于判断参数是否满足指定的条件。T 为入参类型,出参为 boolean 类型 |
Function<T, R> |
函数式接口,通常用于对参数进行处理、转换(处理逻辑由 Lambda 表达式实现),然后返回一个新的值。T 为入参类型,R 为出参类型 |
4.1、Supplier 接口
方法 |
描述 |
T get() |
该方法不需要参数,它会按照某种实现逻辑返回一个数据(由 Lambda 表达式实现) |
示例:
| public class Test_03 { |
| public static void main(String[] args) { |
| String name = getString(() -> "勋悟空"); |
| System.out.println("name = " + name); |
| |
| Integer age = getInteger(() -> 500); |
| System.out.println("age = " + age); |
| } |
| |
| |
| public static String getString(Supplier<String> sup) { |
| return sup.get(); |
| } |
| |
| |
| public static Integer getInteger(Supplier<Integer> sup) { |
| return sup.get(); |
| } |
| |
| |
| } |
运行:
4.2、Consumer 接口
方法 |
描述 |
void accept(T t) |
对给定的参数执行此操作 |
default Consumer andThen(Consumer after) |
依次执行此操作,然后执行 after 操作 |
示例:
| public class Test_05 { |
| public static void main(String[] args) { |
| |
| operatorString("勋悟空", System.out::println); |
| |
| |
| operatorString("勋悟空", System.out::println, s -> System.out.println(s.length())); |
| } |
| |
| |
| public static void operatorString(String name, Consumer<String> con) { |
| con.accept(name); |
| } |
| |
| |
| public static void operatorString(String name, Consumer<String> con1, Consumer<String> con2) { |
| |
| |
| |
| |
| con1.andThen(con2).accept(name); |
| } |
| } |
运行:
4.3、Predicate 接口
方法 |
描述 |
boolean test(T t) |
对给定的参数进行判断,返回一个布尔值(判断逻辑由 Lambda 表达式实现) |
default Predicate negate() |
返回一个逻辑的否定,对应 逻辑非( ! ) |
default Predicate and(Predicate other) |
返回一个组合判断,对应 短路与(&&) |
default Predicate or(Predicate other) |
返回一个组合判断,对应 短路或(||) |
示例:
| public class Test_07 { |
| public static void main(String[] args) { |
| |
| boolean b1 = checkString1("hello", s -> s.length() > 6); |
| boolean b2 = checkString1("hello", s -> s.length() < 6); |
| |
| |
| boolean b3 = checkString2("hello", s -> s.length() > 6); |
| boolean b4 = checkString2("hello", s -> s.length() < 6); |
| |
| |
| boolean b5 = checkString3("hello", s -> s.length() > 6, s -> s.length() < 6); |
| boolean b6 = checkString3("hello", s -> s.length() > 3, s -> s.length() < 6); |
| |
| |
| boolean b7 = checkString4("hello", s -> s.length() > 6, s -> s.length() < 6); |
| boolean b8 = checkString4("hello", s -> s.length() > 3, s -> s.length() < 6); |
| } |
| |
| |
| public static boolean checkString1(String s, Predicate<String> pre) { |
| return pre.test(s); |
| } |
| |
| |
| public static boolean checkString2(String s, Predicate<String> pre) { |
| return pre.negate().test(s); |
| } |
| |
| |
| public static boolean checkString3(String s, Predicate<String> pre1, Predicate<String> pre2) { |
| return pre1.and(pre2).test(s); |
| } |
| |
| |
| public static boolean checkString4(String s, Predicate<String> pre1, Predicate<String> pre2) { |
| return pre1.or(pre2).test(s); |
| } |
| } |
运行:
| b1 = false |
| b2 = true |
| -------- |
| b3 = true |
| b4 = false |
| -------- |
| b5 = false |
| b6 = true |
| -------- |
| b7 = true |
| b8 = true |
4.4、Function 接口
方法 |
描述 |
R apply(T t) |
将此函数应用于给定的参数 |
default Function andThen(Function after) |
返回一个组合函数,首先将该函数应用于输入,然后将 after 函数应用于结果 |
示例:
| public class Test_09 { |
| public static void main(String[] args) { |
| |
| convert("1", Integer::parseInt); |
| |
| |
| convert(1, i -> String.valueOf(i + 10)); |
| |
| |
| convert("1", Integer::valueOf, s -> String.valueOf(s + 100)); |
| } |
| |
| |
| public static void convert(String s, Function<String, Integer> fun) { |
| Integer i = fun.apply(s); |
| System.out.println("i = " + i); |
| } |
| |
| |
| public static void convert(int i, Function<Integer, String> fun) { |
| String s = fun.apply(i); |
| System.out.println("s = " + s); |
| } |
| |
| |
| public static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) { |
| String ss = fun1.andThen(fun2).apply(s); |
| System.out.println("ss = " + ss); |
| } |
| } |
运行:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)