java8的大多数函数式接口都在java.util.function
包下。java
@FunctionalInterface public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
Function函数会获得一个参数,并返回一个结果,函数的方法是
void apply();
若是一个函数,接收一个函数做为参数,或者返回一个函数做为返回值,那么这个函数就叫作高阶函数。app
R apply(T t);
apply的语义为:将函数应用到给定的参数上,T为函数的输入类型,R为函数的返回类型函数
public int compute(int a, Function<Integer, Integer> function){ return function.apply(a); } public String convert(int a, Function<Integer, Integer> function){ return function.apply(a); } compute(1, value -> 2 * value); convert(5, value -> String.valueOf(value + helloworld)); Function<Integer, Integer> function = value -> value * value; compute(5,function);
Function不须要在设计时考虑到全部的行为,在使用的时候,用户能够按照本身的思考来传递行为,在调用前根本就不须要知道行为是什么。ui
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); }
compose组合
函数首先对输入应用before
Function,而后再应用当前函数。是实际上造成了两个function的串联。this
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
andThen
与compose
正好相反,是先对输入应用this.apply,而后再应用参数的after
Function。设计
Function
中的andThen
与compose
实际上是为了实现一种业务场景:须要屡次调用某几个Function,而Function.apply直接将结果返回,andThen
与compose
返回的依旧是Function。code
BiFunction
其实就是Function的一种强化版,能够同时接受两个参数进行操做,并返回一个结果。对象
R apply(T t, U u);
接受 T 和 U ,返回 R继承
public compute(int a, int b, BiFunction<Integer, Integer, Integer> biFuncion){ return biFunction.apply(a, b); } test.compute(1, 2, (value1, value2) -> value1 + value2);
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)); }
有意思的是,BiFunction的andThen方法,参数是Function而不是BiFunction。这是因为:andThen的语义为先执行this.apply,即BiFunction的apply,因为BiFunction的apply返回结果只有一个值R
,而这个值又是做为参数传入给after
,因为BiFunction须要接受两个参数,因此after
必须是只须要接受一个参数的Function。
这也是BiFunction没有compose
方法的主要缘由,由于不管BiFunction仍是Function,返回的结果只有一个,因此没法应用到当前的BiFunction上。接口
public class Person{ private String userName; private int age; } public class Test{ public static void main(String[] args){ Person p1 = new Person("a", 10); Person p2 = new Person("b", 20); Person p3 = new Person("c", 30); List<Person> list = Arrays.asList(p1, p2, p3); Test test = new Test(); // List<Person> res1 = test.getPersonsByUserName("a", list); // List<Person> res2 = test.getPersonsByAge("a", list); List<Person> res3 = test.getPersonsByAge2(20, list, (age, personList) -> { return personList.stream().filter(person -> person.getAge() >= age).collect(Collectors.toList()); }); List<Person> res4 = test.getPersonsByAge2(20, list, (age, personList) -> { return personList.stream().filter(person -> person.getAge() < age).collect(Collectors.toList()); }); } // 方式一,经过流的filter public List<Person> getPersonsByUserName(String userName, List<Person> persons){ return persons.stream().filter(person -> person.getUserName().equals(userName)).collect(Collectors.toList()); } // 方式二,经过BiFunctionb包装 public List<Person> getPersonsByAge(int age, List<Person> persons){ BiFunction<Integer, List<Person>, List<Person>> biFunction = (a ,l) -> { return l.stream().filter(person -> person.getAge() >= a).collect(Collectors.toList()); }; return biFunction.apply(age, persons); } // 方式三,经过接收BiFunction public List<Person> getPersonsByAge2(int age, List<Person> persons, BiFunction<Integer, List<Person>, List<Person>> biFunction){ return biFunction.apply(age, persons); } }
若是经过方法三来实现,将方法的实现反转给调用者,调用者能够更灵活的规范他想要筛选数据的方式和条件。
@FunctionalInterface public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> negate() { return (t) -> !test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
predicate接受一个参数,并返回一个boolean。
Predicate<String> predicate = p -> p.length() > 5; predicate.test("aaaaaa"); List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); conditionFilter(list, p -> p % 2 ==0); public void conditionFilter(List<Integer> list, Predicate<Integer> predicate){ list.forEach(i -> { if(predicate.test(i)){ System.out.println(i); } }) } // isEqual 方法使用 System.out.println(Predicate.isEqual("test").test("test"));
表示一个结果的供应者,并无要求提供与之前不一样的结果。不接受任何参数,并返回一个结果。
public interface Supplier<T>{ T get(); }
在开发时supplier能够用于工厂
,不接受参数并返回实例。
public class Student { private String name; private Intger age; } public class StudentTest{ // 经过supplier调用 student的构造方法 Supplier<Student> supplier = () -> new Student(); supplier.get().getName(); Supplier<Student> supplier2 = Student::new; supplier2.get().getName(); }
对于Supplier来讲,须要不接受参数,而且返回结果。因此若是对象中没有无参构造方法,编译器则会报错。
@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } }
BinaryOperator
继承了BiFunction
。可是BinaryOperator是一种特殊的BiFunction,它的三个类型都一致。
minBy
接受了一个Comparator函数式接口
,返回一个BinaryOperator类型对象,是两个入参中更小的那个,判断的标准来自于Comparator比较规则。maxBy则相反。
public class Test { public static void main(String[] args) { Test test = new Test(); System.out.println(test.cul("avv", "bbbbb", Comparator.comparingInt(String::length))); System.out.println(test.cul("avv", "bbbbb", (a, b) -> a.charAt(0) - b.charAt(0))); System.out.println(test.cul("avv", "bbbbb", Comparator.comparingInt(a -> a.charAt(0)))); } public String cul(String a, String b , Comparator<String> comparator){ return BinaryOperator.minBy(comparator).apply(a,b); } }
函数式接口是JDK8中的Stream和Optional等内容的基础。以上这几个是其余函数式接口的基础。