Java 8 function包 部分函数介绍
最近看公司推荐代码,许多的模板类采用函数式编程的方式,借着疑问看了下Java8 function 包相关知识。
接口 | 解释 |
Function<T, R> | 接收T对象,返回R对象 |
Consumer<T> | 接收T对象,无返回值 |
Predicate<T> | 接收T对象,返回boolean值 |
Supplier<T> | 提供T对象(如工厂),不接受值 |
BiFunction<T, U, R> | 接收T对象&U对象,返回R对象 |
UnaryOperator<T> | 接收T对象,返回T对象,继承于Function |
BinaryOperator<T> | 接收两个T对象,返回T对象,继承于BiFunction |
标注为FunctionalInterface的接口被称为函数式接口,该接口只能有一个自定义方法(未实现的方法),所有标注了该注解的接口都将能用在lambda表达式 :
- 改注解只能标记在有且仅有一个抽象方法接口上;
- JDK8接口中的静态方法(static)和默认方法(default),均不为抽象方法;
- Java所有的类均继承Object,接口显示声明覆盖Object中的方法,也不算抽象方法;
- 如果接口符合“函数式接口”规范,不加@FunctionalInterface也为函数式接口,有改注解会进行编译器检查。违反函数式接口定义,即使加上该注解,编译器依旧会报错。即@FunctionalInterface非必须
补充:接口中所有的方法默认为public,所有的参数默认为是static和final的参数
一、Function<T, R>
@FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * Returns a function that always returns its input argument. * * @param <T> the type of the input and output objects to the function * @return a function that always returns its input argument */ static <T> Function<T, T> identity() { return t -> t; }
一、Function<T, R>
Function<T, R>属于泛型类,T代表传入的对象,R代表返回的结果对象。大致意思为传入T经过某些逻辑处理,最终返回R 有点类似 y = f(x)的关系该Function(f)就是所定义的从T(x)到R(y)的逻辑处理关系(一元方程组)。所以Function中没有具体的操作,具体的操作需要我们去为它指定,因此apply具体返回的结果取决于传入的lambda表达式
1、apply方法 -- apply用于执行从T到R所定义的逻辑关系。所以Function中没有具体的操作,具体的操作需要开发人员去指定,因此具体的返回结果取决于传入的lamdba表达式。
R apply(T t);
2、compose方法 -- compose接收一个Function参数,返回时先用传入的逻辑执行apply,然后使用当前Function的apply。
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); }
例子:
public void testCompose(){ Function<Integer,Integer> A=i->i+1; Function<Integer,Integer> B=i->i*i; System.out.println(B.compose(A).apply(4)); /* 结果为25 */ }
3、andThen方法 -- andThen跟compose方法执行顺序相反,andThen先执行当前的逻辑,再执行参数传入的逻辑。
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
例子:
public void testAndThen(){ Function<Integer,Integer> A=i->i+1; Function<Integer,Integer> B=i->i*i; System.out.println(B.andThen(A).apply(4)); /* 结果为17 */ }
4、 identity方法 -- identity方法用于返回输出跟输入一样的lambda表达式对象,一般个人使用比较多的情况是stream流转map过程中key覆盖问题时使用。
static <T> Function<T, T> identity() { return t -> t; }
二、Consumer<T>
@FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
1、accept -- accept方法跟Function<T, R>的apply方法差别为无返回值。
例子:
AcceptTest acceptTest = new AcceptTest("ID_小汤","博客园");//构造函数参数1为属性name 参数2为属性origin Consumer<AcceptTest> consumerFun = o -> o.setName("Tony"); consumerFun.accept(acceptTest); System.out.println(acceptTest.getName()); //输出值为Tony
2、andThen -- andThen方法跟Function<T, R>的andThen含义相同,为先执行当前定义accept逻辑,然后再执行传入的accept定义逻辑。
例子:
AcceptTest acceptTest = new AcceptTest("ID_小汤","博客园");//构造函数参数1为属性name 参数2为属性origin Consumer<AcceptTest> consumerFun1 = o -> o.setName("Tony"); Consumer<AcceptTest> consumerFun2 = o -> o.setName("小汤"); //先做 consumerFun1 的操作,再做 consumerFun12的操作 consumerFun1.andThen(consumerFun2).accept(acceptTest); System.out.println(acceptTest.getName()); //输出值为 小汤
三、Predicate<T>
@FunctionalInterface public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate<T> negate() { return (t) -> !test(t); } /** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param <T> the type of arguments to the predicate * @param targetRef the object reference with which to compare for equality, * which may be {@code null} * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
1、test方法 -- test方法根据自定义的逻辑当参数去返回true/false。
boolean test(T t);
例子:
User user = new User(); //初始化属性age = 20; name = "ID_小汤";company = "苏宁易购" Predicate<Test> predicate = o -> o.getAge() < 20; System.out.print(predicate.test(user));
2、and方法 -- 两个逻辑与合并(类似SQL的and逻辑)
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
例子:
String otherCompany = "阿里巴巴"; User user = new User();// name = "ID_小汤" age = "20" company = "苏宁易购" Predicate<User> predicate1 = o -> o.getAge() < 20; //逻辑函数1 Predicate<User> predicate2 = o -> otherCompany.equals(o.getCompany()); //逻辑函数2 System.out.print(predicate1.and(predicate2).test(user)); //逻辑与 结果为false
3、negate方法 -- 是Predicate的test方法结果取反
default Predicate<T> negate() {
return (t) -> !test(t);
}
例子:
User user = new User(); // name = "ID_小汤" age = "20" company = "苏宁易购" Predicate<User> predicate = o -> o.getAge() < 20; //逻辑函数1 System.out.print(predicate.negate().test(user));
4、or方法 -- 用于多逻辑函数或逻辑 (类似SQL的or逻辑)
default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); }
例子:
String otherCompany = "阿里巴巴"; User user = new User(); // name = "ID_小汤" age = "20" company = "苏宁易购" Predicate<User> predicate1 = o -> o.getAge() < 20; //逻辑函数1 Predicate<User> predicate2 = o -> otherCompany.equals(o.getCompany()); //逻辑函数2 System.out.println(predicate1.or(predicate2).test(user)); //逻辑与 结果为false
5、isEqual方法 -- 用于根据定义逻辑判断条件是否相同(euqals)
static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
例子:
User user = new User(); // name = "ID_小汤" age = "20" company = "苏宁易购" Predicate<User> predicate = Predicate.isEqual(user); //在集合中找出与user相同的对象 equals 和 hashcode已重写 名字相同变相同 List<User> sameUserList = userList.stream().filter(predicate).collect(Collectors.toList());
四、Supplier<T>
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
1、get方法 -- 用于返回一个对象(有点像工厂的意思)
例子:
/* 常规new方式 开始 */ User user1 = new User(); User user2 = new User(); System.out.println("user1:"+user1.getAge() + " user2:"+user2.getAge()+" user1==user2:"+(user1==user2)); //user1:18 user2:18 user1==user2:false /* Supplier生成对象 开始 */ Supplier<User> s = () -> new User(); user1 = s.get(); user2 = s.get(); //System.out.println("user1:"+s.get().getAge() + " user2:"+s.get().getAge()); System.out.println("user1:"+user1.getAge() + " user2:"+user2.getAge()+" user1==user2:"+(user1==user2)); //user1:18 user2:18 user1==user2:false
五、BiFunction<T, U, R>
/** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result */ R apply(T t, U u); /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null */ 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、R apply(T t,U u) -- 传入参数 t,u 按照某种函数关系(有点二元方程组的意思),返回结果。
例子:
BiFunction<Integer,Integer,Integer> biFunction = (Integer1, Integer2) ->Integer1 * Integer2; Function<Integer,Integer> function = y -> y*5; System.out.println("结果1:"+biFunction.apply(3, 5)); //15
2、andThen -- 用于先按照定义的biFunction执行apply以后,用前面的返回值,再按照定义的function关系执行,返回最终的结果。
例子:
BiFunction<Integer,Integer,Integer> biFunction = (Integer1, Integer2) ->Integer1 * Integer2; Function<Integer,Integer> function = y -> y*5; System.out.println("结果2:"+biFunction.andThen(function).apply(3,5 )); //75
六、UnaryOperator 继承自Function 该函数为一元函数,与父函数Function的区别主要在identity方法泛型上,返回值及关系都是一样的。
@FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> { /** * Returns a unary operator that always returns its input argument. * * @param <T> the type of the input and output of the operator * @return a unary operator that always returns its input argument */ static <T> UnaryOperator<T> identity() { return t -> t; } }
七、BinaryOperator 继承自BiFunction 二元函数,用于接收两个参数,按照某种关系(lambda表达式),执行并返回一个T类型的返回值。
@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { /** * Returns a {@link BinaryOperator} which returns the lesser of two elements * according to the specified {@code Comparator}. * * @param <T> the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the lesser of its operands, * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } /** * Returns a {@link BinaryOperator} which returns the greater of two elements * according to the specified {@code Comparator}. * * @param <T> the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the greater of its operands, * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } }
1、minBy -- 用于返回两个参数中的较小者
例子:
BinaryOperator binaryOperator = BinaryOperator.minBy(Comparator.naturalOrder()); System.out.println(binaryOperator.apply(3, 4)); //3
2、maxBy -- 用于返回两个参数中的较大者
例子:
BinaryOperator binaryOperator = BinaryOperator.maxBy(Comparator.naturalOrder()); System.out.println(binaryOperator.apply(3, 4)); //4