一. 函数式接口
-
概念
函数式接口在java中指的是:有且只有一个抽象方法的接口。
-
@FunctionalInterface注解
java8中专门为函数式接口引入一个新的注解,叫**@FunctionalInterface**,该注解用在接口的定义上
比如:
@FunctionalInterface public interface Animal { public abstract void eat(); // public abstract void walk(); }
注意:一旦使用了这个FunctionalInterface注解定义接口,编译器就会检查接口是否有且只有一个抽象方法,没有满足的话就会报错。(但是即使没有使用这个注解,只要接口满足函数接口的要求,仍是一个函数接口,加这个注解只是帮助检查)
-
关于接口中的static方法和default方法
-
static方法
java8中接口可以定义一个或多个static方法,使用方法和普通static方法一样。
注意:实现接口的类或者子接口是不会继承接口中的静态方法的。
-
default方法
java8在接口中新增的default定义方法,default默认方法不是抽象方法,不会影响函数接口的判断。
定义的default方法,子接口或实现类可以不需要实现,直接调用,也可以重写这个default定义的方法(重写时候不需要加default关键字)。
注意:函数式接口中有且只能有一个抽象方法,但可以有多个static方法或default方法。
-
二. 常用函数式接口
常用的函数式接口主要在包java.util.function
中提供,主要有以下几种常用接口。
-
Supplier<T>–供给型接口
-
抽象方法
T get()
:返回指定泛型的数据由于Supplier是一个函数式接口,意味着使用Lambda表达式时需要供给一个符合泛型类型的对象数据。
import java.util.function.Supplier; public class FunctionInterfaceDemo { public static void main(String[] args) { String str1 = "Hello"; String str2 = "Java"; String s = strConcat(()-> str1 + str2); System.out.println(s); } // 拼接字符串 public static String strConcat(Supplier<String> supplier) { return supplier.get(); } }
其实就是使用函数式接口作为函数参数,调用时使用Lambda表达式实现函数式接口的抽象方法。
而Supplier的抽象方法get是返回一个泛型类型的数据对象,这里是String,所以返回一个String。
-
-
Consumer<T>–消费型接口
-
抽象方法
void accept(T t)
:对给定的参数执行此操作(消费数据t) -
默认方法
default Consumer<T> andThen(Consumer<? supper T> after)
:组合消费,先执行调用andThen接口的对象的accept方法,再执行after中的accept方法。
accept()使用实例:
import java.util.function.Consumer;; public class FunctionInterfaceDemo { public static void main(String[] args) { String str = "Hello World"; consumeStr(str, (s) -> System.out.print(s)); } // 消费字符串 public static void consumeStr(String str, Consumer<String> consumer) { consumer.accept(str); } }
andThen()使用实例:
import java.util.function.Consumer;; public class FunctionInterfaceDemo { public static void main(String[] args) { String str = "Hello World"; consumeStr(str, (s) -> System.out.println(s.toUpperCase()), (s) -> System.out.println(s.toLowerCase())); } // 消费字符串,先变大写,再变小写 public static void consumeStr(String str, Consumer<String> con1, Consumer<String> con2) { con1.andThen(con2).accept(str); } }
-
-
Predicate<T>–断言型接口
-
抽象方法
boolean Test(T t)
:传入一个参数,返回一个布尔值 -
默认方法
default Predicate<T> and(Predicate<? super T> other)
:相当于逻辑运算中的与&&,当两个Predicate函数返回结果都是true时才返回true。default Predicate<T> or(Predicate<? super T> other)
:相当于逻辑运算中的或||,当两个Predicate函数返回结果有一个为true,则返回true,否则返回false。default Predicate<T> negate()
:相当于逻辑运算中的!,就是取反的意思。
test()实例:
import java.util.function.Predicate;;; public class FunctionInterfaceDemo { public static void main(String[] args) { Predicate<Integer> predicate1 = (t) -> t > 0; // 执行test方法,会将参数10 进行 t>0 判断,结果返回true System.out.println(predicate1.test(10)); } }
and(),or(),negate()实例:
import java.util.function.Predicate;;; public class FunctionInterfaceDemo { public static void main(String[] args) { /** * 两个条件同时成立: * 1. 字符串长度大于5 * 2. 以'A'开头 */ String[] array = {"Hello", "Air", "Apple", "Another"}; Predicate<String> pre1 = (t) -> t.length() > 5; Predicate<String> pre2 = (t) -> t.startsWith("A"); for (String s : array) { if(pre1.and(pre2).test(s) == true) { System.out.println(s); } } // 输出Another System.out.println("---------------"); /** * 只要有一个条件成立: * 1. 字符串长度大于5 * 2. 以'A'开头 */ for (String s : array) { if(pre1.or(pre2).test(s) == true) { System.out.println(s); } } // 输出Air,Apple,Another System.out.println("---------------"); /** * 取反: * 1. 字符串长度大于5 */ for (String s : array) { if(pre1.negate().test(s) == true) { System.out.println(s); } } // 输出Hello,Air,Apple } }
-
-
Function<T,R>–函数型接口
该接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
-
抽象方法
R accept(T t)
:根据类型T的参数获取参数类型R的结果。 -
默认方法
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
:组合操作,先执行调用andThen函数的对象的apply方法,然后再执行参数after中的apply方法。default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
:与andThen相反,先调用before中的apply方法,再调用执行compose方法的对象中的apply方法。
import java.util.function.Function; public class FunctionInterfaceDemo { public static void main(String[] args) { Function<Integer, Integer> func = (t) -> t * 2; System.out.println(func.apply(8)); // 输出 16 System.out.println("------------"); Function<Integer,Integer> fun1 = (t) -> t * t; Function<Integer,Integer> fun2 = (t) -> t + 2; // andThen和compose是相反的操作,相同的参数,结果完全不一样 System.out.println(fun1.andThen(fun2).apply(8)); // 输出 66 System.out.println(fun1.compose(fun2).apply(8)); // 输出 100 } }
-