函数接口有一个很简单的定义就是只有一个抽象函数
的接口,函数接口使用注解 @FunctionalInterface
进行声明(注解声明不是必须的,如果没有注解,也是只有一个抽象函数,依旧会被认为是函数接口)。多一个或者少一个抽象函数都不能定义为函数接口,如果使用了函数接口注解又不止一个抽象函数,那么编译器会拒绝编译。函数接口在使用时候可以隐式的转换成 Lambda 表达式。
Java 8
中很多有很多不同功能的函数接口定义,都放在了 Java 8
新增的 java.util.function
包内。下面是一些关于 Java 8
中函数接口功能的描述。
函数式接口 |
描述 |
BiConsumer |
代表了一个接受两个输入参数的操作,并且不返回任何结果 |
BiFunction |
代表了一个接受两个输入参数的方法,并且返回一个结果 |
BinaryOperator |
代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
BiPredicate |
代表了一个两个参数的 boolean 值方法 |
BooleanSupplier |
代表了 boolean 值结果的提供方 |
Consumer |
代表了接受一个输入参数并且无返回的操作 |
DoubleBinaryOperator |
代表了作用于两个 double 值操作符的操作,并且返回了一个 double 值的结果。 |
DoubleConsumer |
代表一个接受 double 值参数的操作,并且不返回结果。 |
DoubleFunction |
代表接受一个 double 值参数的方法,并且返回结果 |
DoublePredicate |
代表一个拥有 double 值参数的 boolean 值方法 |
DoubleSupplier |
代表一个 double 值结构的提供方 |
DoubleToIntFunction |
接受一个 double 类型输入,返回一个 int 类型结果。 |
DoubleToLongFunction |
接受一个 double 类型输入,返回一个 long 类型结果 |
DoubleUnaryOperator |
接受一个参数同为类型 double, 返回值类型也为 double 。 |
Function |
接受一个输入参数,返回一个结果。 |
IntBinaryOperator |
接受两个参数同为类型 int, 返回值类型也为 int 。 |
IntConsumer |
接受一个 int 类型的输入参数,无返回值 。 |
IntFunction |
接受一个 int 类型输入参数,返回一个结果 。 |
IntPredicate |
接受一个 int 输入参数,返回一个布尔值的结果。 |
IntSupplier |
无参数,返回一个 int 类型结果。 |
IntToDoubleFunction |
接受一个 int 类型输入,返回一个 double 类型结果 。 |
IntToLongFunction |
接受一个 int 类型输入,返回一个 long 类型结果。 |
IntUnaryOperator |
接受一个参数同为类型 int, 返回值类型也为 int 。 |
LongBinaryOperator |
接受两个参数同为类型 long, 返回值类型也为 long。 |
LongConsumer |
接受一个 long 类型的输入参数,无返回值。 |
LongFunction |
接受一个 long 类型输入参数,返回一个结果。 |
LongPredicate |
接受一个 long 输入参数,返回一个布尔值类型结果。 |
LongSupplier |
无参数,返回一个结果 long 类型的值。 |
LongToDoubleFunction |
接受一个 long 类型输入,返回一个 double 类型结果。 |
LongToIntFunction |
接受一个 long 类型输入,返回一个 int 类型结果。 |
LongUnaryOperator |
接受一个参数同为类型 long, 返回值类型也为 long。 |
ObjDoubleConsumer |
接受一个 object 类型和一个 double 类型的输入参数,无返回值。 |
ObjIntConsumer |
接受一个 object 类型和一个 int 类型的输入参数,无返回值。 |
ObjLongConsumer |
接受一个 object 类型和一个 long 类型的输入参数,无返回值。 |
Predicate |
接受一个输入参数,返回一个布尔值结果。 |
Supplier |
无参数,返回一个结果。 |
ToDoubleBiFunction |
接受两个输入参数,返回一个 double 类型结果 |
ToDoubleFunction |
接受一个输入参数,返回一个 double 类型结果 |
ToIntBiFunction |
接受两个输入参数,返回一个 int 类型结果。 |
ToIntFunction |
接受一个输入参数,返回一个 int 类型结果。 |
ToLongBiFunction |
接受两个输入参数,返回一个 long 类型结果。 |
ToLongFunction |
接受一个输入参数,返回一个 long 类型结果。 |
UnaryOperator |
接受一个参数为类型 T, 返回值类型也为 T。 |
Function
Function 接口位于包 java.util.function
下。 Function
接口中定义了一个 R apply(T t)
方法,它可以接受一个泛型 T 对象,返回一个泛型 R 对象,即参数类型和返回类型可以不同。
Java 8 源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @FunctionalInterface public interface Function<T, R> {
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)); }
static <T> Function<T, T> identity() { return t -> t; } }
|
apply()方法
示例: 输入一个字符串 <T> String
, 返回字符串的大写形式 <R> String
。
1 2 3 4 5 6
| @Test void functionTestApply() { Function<String, String> toUpperCase = str -> str.toUpperCase(); String result = toUpperCase.apply("www.hglll.top"); FunctionTest.log.info(result); }
|
andThen()方法
示例: 输入一个字符串,获取字符串的长度,然后乘上 2。
1 2 3 4 5 6
| @Test void functionTestAndThen() { Function<String, Integer> len = str -> str.length(); Function<Integer, Integer> doubleLen = num -> num * 2; FunctionTest.log.info(len.andThen(doubleLen).apply("hglll.com").toString()); }
|
Supplier
Supplier
无参数,返回值类型为泛型 T。Supplier
使用场景比较单一。Supplier
由于没有参数输入,所以多用于对象创建,类似于一个对象创建工厂。可以使用 Lambda
方式创建任意对象,也可以使用对象构造方法的方法引用创对象
Java 8 源码
1 2 3 4 5 6 7
| package java.util.function;
@FunctionalInterface public interface Supplier<T> {
T get(); }
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Test void supplierTestGet() { User user = this.userFactory(() -> new User()); SupplierTest.log.info(user.toString()); }
@NotNull private User userFactory(@NotNull Supplier<? extends User> supplier) { User user = supplier.get(); user.setAge(12); user.setName("张三"); return user; }
@Data static final class User { private String name; private Integer age; }
|
BiFunction
BiFunction
和 Function
函数接口十分相似,它可以接受两个不同类型的参数(泛型 T 类型和 泛型 U 类型),然后返回一个其他类型的值(泛型 R 类型)。
Java 8源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package java.util.function;
import java.util.Objects;
@FunctionalInterface public interface BiFunction<T, U, R> {
R apply(T t, U u);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); } }
|
示例: 接收两个字符串,返回字符串的长度和
1 2 3 4 5 6
| @Test void biFunctionTest_1() { BiFunction<String, String, Integer> lengthFun = (s1, s2) -> s1.length() + s2.length(); Integer length = lengthFun.apply("BiFunction", "test"); log.info("字符串长度:{}", length); }
|
输出结果
BiFunction 和 Function
BiFunction
中的 andThen
方法可以接收一个 Function
参数,使用 andThen
时的运算逻辑,是把 BiFunction
的结果传入 Function
运算。
示例 1: 使用 BiFunction
,输入两个字符串,返回两个字符串的长度和;长度和输入到 Function
,拼接上字符串 ” 长度和:“ 返回,然后输出这个结果。
1 2 3 4 5 6 7 8
| @Test void biFunctionTest_2() { BiFunction<String, String, Integer> lengthBiFun = (s1, s2) -> s1.length() + s2.length(); Function<Integer, String> function = s -> "字符串长度:" + s; String result = lengthBiFun.andThen(function).apply("BiFunction", "Function"); log.info(result); }
|
输出结果
示例 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test void biFunctionTest_3() { String result = Study1ApplicationTests.convert("BiFunction", "Function", (s1, s2) -> s1.length() + s2.length(), r1 -> "字符串长度:" + r1); log.info(result); }
public static <T1, T2, R1, R2> R2 convert(T1 t1, T2 t2, BiFunction<T1, T2, R1> biFunction, Function<R1, R2> function) { return biFunction.andThen(function).apply(t1, t2); }
|
工厂模式
要创建的对象类
1 2 3 4 5 6
| @Data @AllArgsConstructor static final class User { private String name; private Integer age; }
|
对象创建工厂
1 2 3 4 5
| public static <R extends User> User userFactory(String name, Integer age, BiFunction<String, Integer, R> biFunction) { return biFunction.apply(name, age); }
|
示例:
1 2 3 4 5 6 7
| @Test void biFunctionTest_4() { User user1 = BiFunctionTest.userFactory("张三", 13, User::new); User user2 = BiFunctionTest.userFactory("李四", 18, User::new); BiFunctionTest.log.info(user1.toString()); BiFunctionTest.log.info(user2.toString()); }
|
输出结果
BiFunctionTest.User(name=张三, age=13) |
BiFunctionTest.User(name=李四, age=18) |
User::new
输入两个参数,要有对应的构造函数 public User(String name, Integer age)
与之对应。
扩展
示例: 构建一个可以过滤指定集合条件的 filter
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @Test void biFunctionTest_5() { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); List<Integer> result1 = filter(list, 2, this::divisible); BiFunctionTest.log.info(result1.toString()); List<Integer> result2 = filter(list, 3, this::divisible); BiFunctionTest.log.info(result2.toString()); List<Integer> result3 = filter(list, 4, this::divisible); BiFunctionTest.log.info(result3.toString()); List<String> stringList = Arrays.asList("java", "node", "c++", "rust"); List<String> stringList1 = filter(stringList, 4, (s, n) -> s.length() == 4 ? true : null); BiFunctionTest.log.info(stringList1.toString()); }
private Boolean divisible(Integer n1, Integer n2) { if (n1 % n2 == 0) { return true; } return null; }
private <T, U, R> List<T> filter(List<T> list, U u, BiFunction<T, U, R> biFunction) { List<T> resultList = new ArrayList<>(); for (T t : list) { if (biFunction.apply(t, u) != null) { resultList.add(t); } } return resultList; }
|
输出结果
BiPredicate
BiPredicate
和 Predicate
函数接口一样,都是返回一个布尔类型,唯一不同的是 Predicate
接受一个参数,而 BiPredicate
可以接受两个不同类型的参数。
Java 8 中源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package java.util.function;
import java.util.Objects; @FunctionalInterface public interface BiPredicate<T, U> { boolean test(T t, U u);
default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) { Objects.requireNonNull(other); return (T t, U u) -> test(t, u) && other.test(t, u); }
default BiPredicate<T, U> negate() { return (T t, U u) -> !test(t, u); }
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) { Objects.requireNonNull(other); return (T t, U u) -> test(t, u) || other.test(t, u); } }
|
test()方法
示例: 判断字符串长度是否是指定长度
1 2 3 4 5 6 7 8 9
| @Test void biPredicateTest_test() { BiPredicate<String, Integer> biFunction = (s, i) -> s.length() == i; System.out.println(biFunction.test("Java", 3)); System.out.println(biFunction.test("Java", 4)); System.out.println(biFunction.test("www.baidu.com", 10)); System.out.println(biFunction.test("www.hglll.top", 14)); }
|
输出结果:false true false false
and()方法
示例: 判断字符串是否以指定字符开头且以指定字符结束
1 2 3 4 5 6 7 8 9
| @Test void biPredicateTest_and() { BiPredicate<String, String> startPredicate = (s1, s2) -> s1.startsWith(s2); BiPredicate<String, String> endPredicate = (s1, s2) -> s1.endsWith(s2); boolean test = startPredicate.and(endPredicate).test("hglll", "w"); System.out.println(test); boolean test1 = startPredicate.and(endPredicate).test("wsw", "w"); System.out.println(test1); }
|
输出结果:false true
BiPredicate 作为参数
示例: 使用 BiPredicate
作为参数,实现对 List 集合的过滤操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @Data @AllArgsConstructor static final class User { private String name; private Integer age; } @Test void biPredicateTest() { List<User> list = new ArrayList<>(); list.add(new User("张三", 23)); list.add(new User("李四", 27)); list.add(new User("赵六", 17)); list.add(new User("五六七", 45)); BiPredicate<String, Integer> age = (n, a) -> a == 2; BiPredicate<String, Integer> name = (n, a) -> "李四".equals(n); BiPredicate<String, Integer> ageAndName = (n, a) -> "五六七".equals(n) || a == 2; System.out.println(BiPredicateTest.filter(list, age)); System.out.println(BiPredicateTest.filter(list, name)); System.out.println(BiPredicateTest.filter(list, ageAndName)); } public static <T extends User> List<T> filter(List<T> list, BiPredicate<String, Integer> biPredicate) { return list.stream() .filter(user -> biPredicate.test(user.getName(), user.getAge())) .collect(Collectors.toList()); }
|
输出结果
UnaryOperator
UnaryOperator
函数接口是 Function
函数接口的扩展,它可以传入一个泛型 T 参数,返回一个泛型 T 结果。
Java 8 源码
1 2 3 4 5 6 7 8 9
| package java.util.function;
@FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> {
static <T> UnaryOperator<T> identity() { return t -> t; } }
|
apply()方法
示例: 分别使用 UnaryOperator
和 Function
把字符串转换为大写形式。
1 2 3 4 5 6 7 8 9 10 11
| @Test void unaryOperatorTestApply() { Function<String, String> upperFun1 = s -> s.toUpperCase(); UnaryOperator<String> upperFun2 = s -> s.toUpperCase();
String res1 = upperFun1.apply("hglll.top"); String res2 = upperFun2.apply("hglll.top");
UnaryOperatorTest.log.info(res1); UnaryOperatorTest.log.info(res2); }
|
输出结果:HGLLL.TOP HGLLL.TOP
identify()方法
不做任何处理,直接返回参数本身,和 Function.identify()
效果一样。
示例: 把字符串集合转换成 key 为大写字符串,value 为字符串本身的 Map(使用 identity 方法返回本身)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Test void unaryOperatorTestIdentity() { Function<String, String> upperFun1 = s -> s.toUpperCase(); UnaryOperator<String> upperFun2 = s -> s.toUpperCase();
List<String> list = Arrays.asList("java", "node", "c++", "rust", "hglll.top");
Map<String, String> map1 = list.stream() .collect(Collectors.toMap(upperFun1::apply, Function.identity()));
Map<String, String> map2 = list.stream() .collect(Collectors.toMap(upperFun2::apply, UnaryOperator.identity()));
Map<String, String> map3 = list.stream() .collect(Collectors.toMap(upperFun2::apply, t -> t));
UnaryOperatorTest.log.info(map1.toString()); UnaryOperatorTest.log.info(map2.toString()); UnaryOperatorTest.log.info(map3.toString()); }
|
UnaryOperator 作为参数
示例 1: 使用 UnaryOperator
作为参数,修改 List 集合中每个元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Test void unaryOperatorTestParam() { List<String> list = Arrays.asList("java", "node", "c++", "rust", "hglll.top"); UnaryOperator<String> upperFun = s -> s.toUpperCase(); List<String> resultList = this.map(list, upperFun); UnaryOperatorTest.log.info(resultList.toString());
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5); UnaryOperator<Integer> doubleInt = i -> i * 2; List<Integer> integers = map(intList, doubleInt); UnaryOperatorTest.log.info(integers.toString()); }
private <T> List<T> map(List<T> list, UnaryOperator<T> unaryOperator) { List<T> resultList = new ArrayList<>(); for (T t : list) { resultList.add(unaryOperator.apply(t)); } return resultList; }
|
示例 2: 使用 UnaryOperator
作为参数,修改 List 集合中每个元素,先转大写,再截取前三位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Test void unaryOperatorTestMultiParam() { List<String> list = Arrays.asList("java", "node", "c++", "rust", "hglll.top"); UnaryOperator<String> upperFun = s -> s.toUpperCase(); UnaryOperator<String> subFun = s -> s.substring(0, 3); List<String> resultList = this.map(list, upperFun, subFun); UnaryOperatorTest.log.info(resultList.toString()); }
private <T> List<T> map(List<T> list, UnaryOperator<T>... unaryOperator) { List<T> resultList = new ArrayList<>(); for (T t : list) { for (UnaryOperator<T> operator : unaryOperator) { t = operator.apply(t); } resultList.add(t); } return resultList; }
|