一、场景
班里考试成绩,按照成绩公布排行榜。
二、示例
1.定义学生,具有名字和成绩属性
public class Student {
private String name;
private int score;
public Student() {
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
//...getting\setting忽略
}
2.定义学生集合,并使用Collections的sort方法传入学生集合list和比较器Compartor进行排序
List<Student> list = new ArrayList<>();
Student studentA = new Student("张三",90);
Student studentB = new Student("王五",80);
Student studentC = new Student("李四",85);
list.add(studentA);
list.add(studentB);
list.add(studentC);
System.out.println(list);
Cections.sort(list,new Compartor<Student>{
@Override
public int compare(Student a, Student b){
return a.getScore() - b.getScore();
}
});
System.out.println(list);
输出:
[Student[name:张三,score:90], Student[name:王五,score:80], Student[name:李四,score:85]]
[Student[name:王五,score:80], Student[name:李四,score:85], Student[name:张三,score:90]]
三、概念定义
1.先来看比较器接口
@FunctionalInterface
public interface Comparator<T> {
**int compare(T o1, T o2);**
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
//... ,其它方法
}
注:@FunctionalInterface并不是标识这个接口只有一个抽象接口方法
2.再来看Collections的sort方法定义
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
注意到定义中这个比较器Compartor是作为Collections的sort的方法参数。而实现中这个参数是匿名类实例
3.lambda语法
匿名类只保留方法参数和方法体,
如:
(Student a ,String b)-> {
return a.getScore() - b.getScore();
}
当返回结果只有一条时,可以忽略{} 和return
(Student a ,String b)-> a.getScore() - b.getScore();
其中可以调用匿名类实例的泛型自动推导出参数类型,故可以省略匿名类方法参数类型。
(a ,b)-> a.getScore() - b.getScore();
Some comparators like (person1, person2) -> person1.getName().compareTo(person2.getName()) could be simplified like this: Comparator.comparing(Person::getName).
同样可以简写为:
Comparator.comparing(Student::getScore);
4.方法引用
Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用
Student增加静态方法
public static int myCompare(Student a,Student b){
return a.getScore() - b.getScore();
}
上面比较器匿名类实例可以用下面方法引用代替
Student::myCompare
注:Student的实例引用,可以用
Student::new
其中构造函数参数的匹配,是自动根据调用匿名类方法参数的情况决定的。
如:
一个用来创建Student对象的对象工厂接口
interface StudentFactory<S extends Student> {
S create(String name, int score);
}
这个接口匿名类实例化过程可以用这种方式
StudentFactory<Stduent> factory = Student::new
其中这个new ,匹配的构造函数为
public Student(String name, int score){
this.name = name;
this.score = score;
}
四、函数式接口实现
1.lambda方式
Collections.sort(list,(a,b)->a.getScore() - b.getScore());
2.方法引用方式
Collections.sort(list,Student::myCompare);
五、总结
函数式接口的匿名类实例作为别的方法参数,可以有lambd表达式和引用方法两种实现方式。这都简化了接口匿名类实例化的代码量,增加了方法的复用性。