自定义比较器
理解: 重写 Comparator 中的 compare 方法。自定义的比较规则:我这里自定义的比较器是: 期望得到 逆序排列 判断条件是:当a<=b时,返回1。否则返回-1;意思就是我期望的是“后一个元素比前一个元素小(即降序)”,如果已经满足,就不需要调换顺序(返回1),如果不满足,就需要调换一下顺序(返回-1)。
new Comparator<Integer>(){
@Override //降序
public int compare(Integer a, Integer b) { //源码中第一个入参(a)是数组靠后面的数,第二个入参(b)是数组靠前面的数
if(a <= b){ //由条件加上返回值来确定是升序还是降序
return 1; //比如这里:原数组后面的数小于前面的数,返回1,1则表示数组中现在的顺序不需要调整。
}else{
return -1; //比如这里:原数组后面的数小于前面的数,返回-1,-1则表示数组中现在的顺序需要调整。
}
}
}
2
3
4
5
6
7
8
9
10
java.util.Comparator
功能接口对对象的集合进行总排序。
为了对一个集合进行排序,我们将比较器(**Comparator**
)实例传递给**Stream.sorted**
、**Collections.sort**
、**List.sort**
和**Arrays.sort**
方法。
比较器(Comparator
)还可以控制SortedSet
的顺序和SortedMap
数据结构的键顺序。
比较器(Comparator
)的功能方法是compare(T o1, T o2)
,当第一个参数小于、等于或大于第二个参数时,返回一个负整数、零或一个正整数。
比较器(Comparator
)施加的排序应与equals
方法一致。
只有当c.compare(e1, e2)==0
对于集合中的每个e1
和e2
具有与e1.equals(e2)
相同的布尔值时,才称为一致,其中c
是比较器(Comparator
)的实例。
# 比较器功能方法:compare(T o1, T o2)
compare
是比较器功能接口的功能方法。从Java
源代码中找到它的声明。
int compare(T o1, T o2)
compare
比较其两个参数的顺序。
当第一个参数小于、等于或大于第二个参数时,它返回负值、零值或正值。
# 1. 使用 Lambda表达式定义 compare
我们使用lambda
表达式定义compare
功能方法如下。
升序写法:
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());
2
降序写法:
Comparator<Student> ageComp = (s1, s2) -> s2.getAge() - s1.getAge();
简化写法:
PriorityQueue<int[]> pq = new PriorityQueue<>((p1,p2) -> p2[1]-p1[1]);//改为降序,大顶堆
Arrays.sort(task,(p1,p2) -> p2[1]-p1[1]);
示例 CompareDemo.java
import java.util.Comparator;
import java.util.List;
public class CompareDemo {
public static void main(String[] args) {
List<Student> list = Student.getStudentList();
System.out.println("--- Sort Students by age ---");
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
list.sort(ageComp);
list.forEach(s -> System.out.println(s));
System.out.println("--- Sort Students by name ---");
Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());
list.sort(nameComp);
list.forEach(s -> System.out.println(s));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
compare
功能方法需要返回-ve
、0
、+ve
的值。
s1.getAge()-s2.getAge()
将返回-ve
、0
、+ve
的值。
而String.compareTo
对两个字符串进行按字母顺序的比较,它返回-ve
、0
、+ve
的值。
List.sort
根据给定的比较器(Comparator
)实例对这个列表进行排序。
现在找到一个在Student
类中使用的示例。
Student.java
import java.util.Arrays;
import java.util.List;
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Student s) {
return name.compareTo(s.getName());
}
@Override
public String toString(){
return name + "-" + age;
}
public static List<Student> getStudentList(){
Student s1 = new Student("Ram", 18);
Student s2 = new Student("Shyam",22);
Student s3 = new Student("Mohan",19);
List<Student> list = Arrays.asList(s1,s2,s3);
return list;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
输出
--- Sort Students by age ---
Ram-18
Mohan-19
Shyam-22
--- Sort Students by name ---
Mohan-19
Ram-18
Shyam-22
2
3
4
5
6
7
8
# 2. 自定义 compare 实现比较器
CompareDemoImplement.java
import java.io.Serializable;
import java.util.Comparator;
import java.util.List;
class AgeComparator implements Comparator<Student>, Serializable {
private static final long serialVersionUID = 1L;
@Override
public int compare(Student s1, Student s2) {
return s1.getAge() - s2.getAge();
}
}
class NameComparator implements Comparator<Student>, Serializable {
private static final long serialVersionUID = 1L;
@Override
public int compare(Student s1, Student s2) {
return s1.getName().compareTo(s2.getName());
}
}
public class CompareDemoImplement {
public static void main(String[] args) {
List<Student> list = Student.getStudentList();
System.out.println("--- Sort Students by age ---");
AgeComparator ageComparator = new AgeComparator();
list.sort(ageComparator);
list.forEach(s -> System.out.println(s));
System.out.println("--- Sort Students by name ---");
NameComparator nameComparator = new NameComparator();
list.sort(nameComparator);
list.forEach(s -> System.out.println(s));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
输出
--- Sort Students by age ---
Ram-18
Mohan-19
Shyam-22
--- Sort Students by name ---
Mohan-19
Ram-18
Shyam-22
2
3
4
5
6
7
8
在实现比较器接口的同时实现Serializable
是一个很好的做法,因为它们可能被用作可序列化数据结构(如TreeSet
和TreeMap
)的排序方法。