Java Comparator

原文:(130条消息) 【Java 8 新特性】Java Comparator | 比较器_猫巳的博客-CSDN博客_javacomparator

比较器的功能方法:Compare(T o1,T o2)

compare是比较器接口的功能方法。

1
int compare(T o1,T o2)

使用Lambda表达式定义compare

1
2
3
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
Comparator<Student> nameComp = (s1, s2) -> s1.getName().compareTo(s2.getName());

实例:

1
2
3
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
list.sort(ageComp);
list.forEach(s -> System.out.println(s));

自定义compare实现比较器(定制排序)

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

在实现比较器接口的同时实现Serializable是一个很好的做法,因为它们可能被用作可序列化数据结构(如TreeSetTreeMap)的排序方法。

什么时候选择定制排序

Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。

个人认为有两种情况可以使用实现Comparator接口的方式:

  1. 对象不支持自己和自己比较(没有实现Comparable接口),但是又想对两个对象进行比较(大都是这种情况)
  2. 对象实现了Comparable接口,但是开发者认为compareTo方法中的比较方式并不是自己想要的那种比较方式;
  • 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
  • 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序

比较器的使用

我们可以用Stream.sortedCollections.sortList.sortArrays.sort方法来使用我们的比较器。

Stream.sorted

功能说明:以自然序或着自定义Comparator 接口排序规则来排序一个流。

1
2
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
list.stream().sorted(ageComp).forEach(s -> System.out.println(s));

Collections.sort

Collections是一个工具类,该集合中的Student对象必须实现Comparable接口(强制),然后实现它的compareTo方法,否则编译器会报错。sort是其中的静态方法,是用来对List类型进行排序的,它有两种参数形式:

1
2
3
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
Collections.sort(list, ageComp);
list.forEach(s -> System.out.println(s));

List.sort

1
2
3
Comparator<Student> ageComp = (s1, s2) -> s1.getAge() - s2.getAge();
list.sort(ageComp);
list.forEach(s -> System.out.println(s));

比较器的方法

reversed

reversed是Java比较器功能接口的默认方法。reversed返回一个比较器,该比较器==强制执行反向排序==。

1
2
3
Comparator<Student> nameComparator = (s1, s2) -> s1.getName().compareTo(s2.getName());
Collections.sort(list, nameComparator.reversed());

reverseOrder

1
2
3
4
5
List<String> strList = Arrays.asList("Varanasi", "Allahabad", "Kanpur", "Noida");
Collections.sort(strList, Comparator.reverseOrder());
strList.forEach(s -> System.out.print(s + " "));
System.out.println("\n-----------");

naturalOrder

Comparator.naturalOrder方法返回一个比较器,该比较器以自然顺序比较可比较的对象。

1
2
3
List<Student> stdList = Student.getStudentList();
stdList.sort(Comparator.naturalOrder());
stdList.forEach(s -> System.out.print(s.getName() + " "));

nullsFirst

  1. 空元素被认为是小于非空元素的。
  2. 当两个元素都是空的时候,那么它们就被认为是相等的。
  3. 当两个元素都是非空的时候,指定的比较器决定了顺序。
  4. 如果指定的比较器是空的,那么返回的比较器认为所有非空的元素是相等的。
1
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
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NullsFirstDemo {
public static void main(String[] args) {
Student s1 = new Student("Ram", 18);
Student s2 = new Student("Shyam", 22);
Student s3 = new Student("Mohan", 17);

System.out.println("-------Case1: One null----------");

List<Student> list = Arrays.asList(s1, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));
list.forEach(s -> System.out.println(s));

System.out.println("--------Case2: More than one null---------");

list = Arrays.asList(s1, null, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));
list.forEach(s -> System.out.println(s));

System.out.println("--------Case3: Reverse specified Comparator to nullsFirst---------");

list = Arrays.asList(s1, null, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName).reversed()));
list.forEach(s -> System.out.println(s));

System.out.println("--------Case4: Reverse Comparator returned by nullsFirst---------");

list = Arrays.asList(s1, null, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)).reversed());
list.forEach(s -> System.out.println(s));

System.out.println("--------Case5: Specify natural order Comparator to nullsFirst---------");

list = Arrays.asList(s1, null, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(Comparator.naturalOrder()));
list.forEach(s -> System.out.println(s));

System.out.println("--------Case6: Specify null to nullsFirst---------");

list = Arrays.asList(s1, null, s2, null, s3);
Collections.sort(list, Comparator.nullsFirst(null));
list.forEach(s -> System.out.println(s));
}
}

1
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
36
-------Case1: One null----------
null
Mohan-17
Ram-18
Shyam-22
--------Case2: More than one null---------
null
null
Mohan-17
Ram-18
Shyam-22
--------Case3: Reverse specified Comparator to nullsFirst---------
null
null
Shyam-22
Ram-18
Mohan-17
--------Case4: Reverse Comparator returned by nullsFirst---------
Shyam-22
Ram-18
Mohan-17
null
null
--------Case5: Specify natural order Comparator to nullsFirst---------
null
null
Mohan-17
Ram-18
Shyam-22
--------Case6: Specify null to nullsFirst---------
null
null
Ram-18
Shyam-22
Mohan-17