A Few Hidden Treasures in Java 8 on YouTube
是一个很有意思的视频。
函数式编程有一个很大的特点就是高阶函数。在很多”函数式“ 语言中,“函数”都是”第一公民“,就是说,函数可以像整数,浮点数,字符串等等普通值一样,可以作为函数的参数,也可以作为成员变量,函数的返回值。
在 JAVA 中,函数当然不是第一公民,函数是只有一个虚成员函数的接口。
如果一个函数的的参数是函数,或者返回值是函数,那么这个函数就是高阶函数。
任何非静态成员函数都可以看成一个函数,第一个参数是 this
。
下面是一个例子
public class SortPersonTest {
public static List<Person> createPeople() {
return Arrays.asList(
new Person("Sara", Person.Gender.FEMALE, 20),
new Person("Sara", Person.Gender.FEMALE, 22),
new Person("Bob", Person.Gender.MALE, 20),
new Person("Paula", Person.Gender.FEMALE, 32),
new Person("Paul", Person.Gender.MALE, 32),
new Person("JACk", Person.Gender.MALE, 2),
new Person("JACK", Person.Gender.MALE, 72),
new Person("Jill", Person.Gender.FEMALE, 12));
}
public static void main(String[] args) {
createPeople().stream().sorted(
Comparator.comparing(Person::getGender)
.reversed()
.thenComparing(Person::getAge)
.thenComparing(Person::getName))
.forEach(System.out::println);
}
}
程序输出
Person(name=Jill, gender=FEMALE, age=12)
Person(name=Sara, gender=FEMALE, age=20)
Person(name=Sara, gender=FEMALE, age=22)
Person(name=Paula, gender=FEMALE, age=32)
Person(name=JACk, gender=MALE, age=2)
Person(name=Bob, gender=MALE, age=20)
Person(name=Paul, gender=MALE, age=32)
Person(name=JACK, gender=MALE, age=72)
sorted
是一个高阶函数,第一个参数是 Stream this
。第二个参数是一个 Comparator
接口,这个接口只有一个虚函数,所以可以认为把一个函数作为参数。
Comparator::comparing
也是一个高阶函数,第一个参数是一个函数(Function),返回值也是一个函数(Comparator)。 类似实现可以是
interface MyComparator<T> extends Comparator<T> {};
public static <T, U extends Comparable<? super U>>
MyComparator<T> comparing( Function<? super T, ? extends U> fKey) {
return (t1, t2) -> fKey.apply(t1).compareTo(fKey.apply(t2));
}
请忽略 Generic 的部分,这个不是本文的重点。
reversed
同样也是一个高阶函数,第一个函数是 Comparator (this) ,返回值还是一个函数 (Comparator),reversed
的实现可以类似下面
default MyComparator<T> myReversed(){
return (t1,t2) -> this.compare(t2,t1);
}
thenComparing
的实现类似下面的代码
default <U extends Comparable<? super U>> MyComparator<T> myThenComparing(Function<? super T, ? extends U> fKey) {
return (t1, t2) -> {
final int r1 = compare(t1, t2);
return r1 == 0 ? myComparing(fKey).compare(t1,t2): r1;
};
}
完整代码
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
public class SortPersonTest {
public static List<Person> createPeople() {
return Arrays.asList(
new Person("Sara", Person.Gender.FEMALE, 20),
new Person("Sara", Person.Gender.FEMALE, 22),
new Person("Bob", Person.Gender.MALE, 20),
new Person("Paula", Person.Gender.FEMALE, 32),
new Person("Paul", Person.Gender.MALE, 32),
new Person("JACk", Person.Gender.MALE, 2),
new Person("JACK", Person.Gender.MALE, 72),
new Person("Jill", Person.Gender.FEMALE, 12));
}
interface MyComparator<T> extends Comparator<T> {
default MyComparator<T> myReversed(){
return (t1,t2) -> this.compare(t2,t1);
}
default <U extends Comparable<? super U>> MyComparator<T> myThenComparing(Function<? super T, ? extends U> fKey) {
return (t1, t2) -> {
final int r1 = compare(t1, t2);
return r1 == 0 ? myComparing(fKey).compare(t1,t2): r1;
};
}
};
public static <T, U extends Comparable<? super U>>
MyComparator<T> myComparing(Function<? super T, ? extends U> fKey) {
return (t1, t2) -> fKey.apply(t1).compareTo(fKey.apply(t2));
}
public static void main(String[] args) {
createPeople().stream().sorted(
myComparing(Person::getGender)
.myReversed()
.myThenComparing(Person::getAge)
.myThenComparing(Person::getName))
.forEach(System.out::println);
}
}