20210121 java.util.Comparator
java.util.Comparator
基本信息
-
@FunctionalInterface public interface Comparator<T>
-
rt.jar
-
引入版本:
1.2
-
相关类:
java.lang.Comparable
、java.io.Serializable
使用说明
- 比较器,可以对某些对象集合施加总排序,会改变集合内元素顺序
- 可以将比较器传递给排序方法(例如
Collections.sort
或Arrays.sort
),以实现对排序顺序的精确控制 - 比较器还可以用于控制某些数据结构(例如排序的 Set 或排序的 Map)的顺序,或为没有自然顺序的对象集合提供排序。
- 注意:比较器通常也可以实现
java.io.Serializable
,这是一个好主意,因为它们可用作可序列化数据结构(如TreeSet
,TreeMap
)中的排序方法。为了使数据结构成功序列化,比较器(如果提供)必须实现Serializable
。 - 与
Comparable
不同,比较器可以选择允许对空参数进行比较,同时保持对等关系的要求。 - 该接口是 Java Collections Framework 的成员。
接口定义方法
接口定义方法 |
---|
int compare(T o1, T o2); 参数: o1 – 要比较的第一个对象。 o2 – 要比较的第二个对象。 返回值: 如果第一个参数小于,等于或大于第二个参数,则为负整数,零或正整数。 |
boolean equals(Object obj); 参数: obj – 与之比较的参考对象。 返回值: 仅当指定对象也是一个 Comparator 并且施加与该比较器相同的顺序时,才返回 true 。 |
int compare(T o1, T o2);
- 比较其两个参数的顺序。当第一个参数小于,等于或大于第二个参数时,返回负整数,零或正整数。
- 必须确保所有 x 和 y 的
sgn(compare(x, y)) == -sgn(compare(y, x))
。 (这意味着,当且仅当compare(x, y)
引发异常时,compare(x, y)
才必须引发异常。) - 必须确保该关系是 可传递的:
((compare(x, y)>0) && (compare(y, z)>0))
意味着compare(x, z)>0
。 - 必须确保对于所有 z
compare(x, y)==0
等同于sgn(compare(x, z))==sgn(compare(y, z))
。 - 注意:一般要求
(compare(x, y)==0) == (x.equals(y))
,任何违反此条件的比较器都应明确指出这一事实
boolean equals(Object obj);
- 此方法必须遵守
Object.equals(Object)
的常规协定。 - 仅当指定对象也是一个
Comparator
并且施加与该比较器相同的顺序时,此方法才能返回true
comp1.equals(comp2)
意味着对于每个对象引用 o1 和 o2 ,sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))
- 注意,不重写
Object.equals(Object)
始终是安全的。 但是,在某些情况下,重写此方法可以通过允许程序确定两个不同的比较器施加相同的顺序来提高性能。
静态方法
静态方法 |
---|
<T extends Comparable<? super T>> Comparator<T> naturalOrder() 返回一个比较器,该比较器以自然顺序比较可比较对象。 返回的比较器是可序列化的, 在比较null时抛出 NullPointerException 。比较对象需要实现 java.lang.Comparable 接口 |
<T extends Comparable<? super T>> Comparator<T> reverseOrder() 与自然顺序相反的比较器 返回的比较器是可序列化的, 在比较null时抛出 NullPointerException 。比较对象需要实现 java.lang.Comparable 接口 |
<T> Comparator<T> nullsFirst(Comparator<? super T> comparator) 返回一个对 null 友好的比较器,该比较器认为 null 小于非 null 。 当两者均为空时,它们被视为相等。 如果两者都不为空,则使用指定的 Comparator 确定顺序。 如果指定的比较器为 null ,则返回的比较器将所有非 null 值视为相等。 如果指定的比较器可序列化,则返回的比较器可序列化。 |
<T> Comparator<T> nullsLast(Comparator<? super T> comparator) 返回一个对 null 友好的比较器,该比较器认为 null 大于非 null 。 当两者均为空时,它们被视为相等。 如果两者都不为空,则使用指定的 Comparator 确定顺序。 如果指定的比较器为 null ,则返回的比较器将所有非 null 值视为相等。 如果指定的比较器可序列化,则返回的比较器可序列化。 |
<T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) 接受一个 Function ,该函数从类型 T 中提取一个实现了 Comparable 的 key,并返回一个 Comparator <T> ,通过该 key 进行比较。 如果传入了参数二比较器,则不需要该 key 实现 Comparable 如果指定的函数也可序列化,则返回的比较器可序列化。 |
<T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) 接受一个 Function ,该函数从类型 T 中提取一个实现了 Comparable 的 int key,并返回一个 Comparator <T> ,通过该 key 进行比较。 如果指定的函数也可序列化,则返回的比较器可序列化。 |
<T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) 接受一个 Function ,该函数从类型 T 中提取一个实现了 Comparable 的 long key,并返回一个 Comparator <T> ,通过该 key 进行比较。 如果指定的函数也可序列化,则返回的比较器可序列化。 |
<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) 接受一个 Function ,该函数从类型 T 中提取一个实现了 Comparable 的 double key,并返回一个 Comparator <T> ,通过该 key 进行比较。 如果指定的函数也可序列化,则返回的比较器可序列化。 |
默认实现方法
默认实现方法 |
---|
Comparator<T> reversed() 返回相反排序顺序的比较器 |
<U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) Comparator<T> thenComparing(Comparator<? super T> other) <U> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) 返回带有另一个比较器的比较器。 如果此比较器认为两个元素相等,即 compare(a, b) == 0 ,则使用参数内容来确定顺序。 |
Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) 同上 |
Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) 同上 |
Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) 同上 |
示例代码
@Test
public void test() {
List<String> strList = Arrays.asList("d", "c", "b", "a");
System.out.println("strList :: " + strList); // strList :: [d, c, b, a]
Comparator<Integer> comparator1 = (o1, o2) -> o1 - o2;
Comparator comparator2 = new MyComparator();
System.out.println(comparator1.equals(comparator2)); // false
Collections.sort(strList, Comparator.naturalOrder());
System.out.println("naturalOrder :: " + strList); // naturalOrder :: [a, b, c, d]
Collections.sort(strList, Comparator.reverseOrder());
System.out.println("reverseOrder :: " + strList); // reverseOrder :: [d, c, b, a]
List<String> strList2 = Arrays.asList("d", "c", "b", "a", null);
System.out.println("strList2 :: " + strList2); // strList2 :: [d, c, b, a, null]
// Collections.sort(strList2, Comparator.naturalOrder()); // NullPointerException
Collections.sort(strList2, Comparator.nullsFirst(Comparator.naturalOrder()));
System.out.println("nullsFirst :: " + strList2); // nullsFirst :: [null, a, b, c, d]
Collections.sort(strList2, Comparator.nullsLast(Comparator.naturalOrder()));
System.out.println("nullsLast :: " + strList2); // nullsLast :: [a, b, c, d, null]
List<ComparatorDTO> dtoList = Arrays.asList(new ComparatorDTO("3", "n1"), new ComparatorDTO("2", "n2"), new ComparatorDTO("1", "n3"));
System.out.println("dtoList :: " + dtoList); // dtoList :: [ComparatorDTO(id=3, name=n1), ComparatorDTO(id=2, name=n2), ComparatorDTO(id=1, name=n3)]
List<ComparatorDTO> dtoList2 = Arrays.asList(new ComparatorDTO("1", "n1"), new ComparatorDTO("2", "n2"), new ComparatorDTO("3", "n3"));
Comparator<ComparatorDTO> comparing1 = Comparator.comparing(ComparatorDTO::getId);
Collections.sort(dtoList, comparing1);
System.out.println("comparing1 :: " + dtoList); // comparing1 :: [ComparatorDTO(id=1, name=n3), ComparatorDTO(id=2, name=n2), ComparatorDTO(id=3, name=n1)]
Collections.sort(dtoList2, comparing1);
System.out.println("comparing1 dtoList2 :: " + dtoList2); // comparing1 dtoList2 :: [ComparatorDTO(id=1, name=n1), ComparatorDTO(id=2, name=n2), ComparatorDTO(id=3, name=n3)]
Comparator<ComparatorDTO> comparing2 = Comparator.comparing(ComparatorDTO::getId, Comparator.reverseOrder());
Collections.sort(dtoList, comparing2);
System.out.println("comparing2 :: " + dtoList); // comparing2 :: [ComparatorDTO(id=3, name=n1), ComparatorDTO(id=2, name=n2), ComparatorDTO(id=1, name=n3)]
List<ComparatorDTO> dtoList3 = Arrays.asList(new ComparatorDTO("3", 3), new ComparatorDTO("2", 1), new ComparatorDTO("1", 2));
System.out.println("dtoList3 :: " + dtoList3); // dtoList3 :: [ComparatorDTO(id=3, name=null, age=3), ComparatorDTO(id=2, name=null, age=1), ComparatorDTO(id=1, name=null, age=2)]
Comparator<ComparatorDTO> comparingInt = Comparator.comparingInt(ComparatorDTO::getAge);
Collections.sort(dtoList3, comparingInt);
System.out.println("comparingInt :: " + dtoList3); // comparingInt :: [ComparatorDTO(id=2, name=null, age=1), ComparatorDTO(id=1, name=null, age=2), ComparatorDTO(id=3, name=null, age=3)]
Comparator<String> reversed = (Comparator<String>) Comparator.naturalOrder().reversed();
Collections.sort(strList, reversed);
System.out.println("reversed :: " + strList); // reversed :: [d, c, b, a]
List<ComparatorDTO> dtoList4 = Arrays.asList(new ComparatorDTO("3", 3), new ComparatorDTO("2", 1), new ComparatorDTO("1", 3));
System.out.println("dtoList4 :: " + dtoList4); // dtoList4 :: [ComparatorDTO(id=3, name=null, age=3), ComparatorDTO(id=2, name=null, age=1), ComparatorDTO(id=1, name=null, age=3)]
Comparator<ComparatorDTO> thenComparing = Comparator.comparing(ComparatorDTO::getAge).thenComparing(ComparatorDTO::getId);
Collections.sort(dtoList4, thenComparing);
System.out.println("thenComparing :: " + dtoList4); // thenComparing :: [ComparatorDTO(id=2, name=null, age=1), ComparatorDTO(id=1, name=null, age=3), ComparatorDTO(id=3, name=null, age=3)]
Comparator<ComparatorDTO> thenComparing2 = Comparator.comparing(ComparatorDTO::getAge).thenComparing(ComparatorDTO::getId, Comparator.reverseOrder());
Collections.sort(dtoList4, thenComparing2);
System.out.println("thenComparing2 :: " + dtoList4); // thenComparing2 :: [ComparatorDTO(id=2, name=null, age=1), ComparatorDTO(id=3, name=null, age=3), ComparatorDTO(id=1, name=null, age=3)]
}