JDK8特性深入学习笔记-函数式接口(2)

微信扫一扫,分享到朋友圈

JDK8特性深入学习笔记-函数式接口(2)

java8的大多数函数式接口都在 java.util.function
包下。

Consumer接口

@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的定义

Function函数会得到一个参数,并返回一个结果,函数的方法是 void apply();

高阶函数

如果一个函数, 接收一个函数作为参数,或者返回一个函数作为返回值
,那么这个函数就叫做高阶函数。

apply

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不需要在设计时考虑到所有的行为,在使用的时候,用户可以按照自己的思考来传递行为,在调用前根本就不需要知道行为是什么。

compose

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的串联。

andThen

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。

BiFunction

BiFunction
其实就是Function的一种强化版,可以同时接受两个参数进行操作,并返回一个结果。

R apply(T t, U u);

接受 T 和 U ,返回 R

通过BiFunction完成两数相加

public compute(int a, int b, BiFunction<Integer, Integer, Integer> biFuncion){
return biFunction.apply(a, b);
}
test.compute(1, 2, (value1, value2) -> value1 + value2);

BiFunction的andThen

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上。

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);
}
}

如果通过方法三来实现,将方法的实现反转给调用者,调用者可以更灵活的规范他想要筛选数据的方式和条件。

Predicate

@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"));

Supplier

表示一个结果的供应者,并没有要求提供与以前不同的结果。不接受任何参数,并返回一个结果。

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来说,需要不接受参数,并且返回结果。所以如果对象中没有无参构造方法,编译器则会报错。

BinaryOperator

@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 与 maxBy

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等内容的基础。以上这几个是其他函数式接口的基础。

AOC推出Nano IPS电竞显示器:2K@165Hz,104% DCI-P3

上一篇

iOS 探索KVO一(几种简单的KVO使用方式)

下一篇

你也可能喜欢

JDK8特性深入学习笔记-函数式接口(2)

长按储存图像,分享给朋友