深入学习java源码之Comparator.reverseOrder()与Comparator.compare()

Comparable接口

此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort (和 Arrays.sort )进行自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。 强烈推荐(虽然不是必需的)使自然排序与 equals 一致。所谓与equals一致是指对于类 C 的每一个 ​​e1​​​ 和 ​​e2​​ 来说,当且仅当 (e1.compareTo((Object)e2) == 0) 与e1.equals((Object)e2) 具有相同的布尔值时,类 C 的自然排序才叫做与 equals 一致 。

Employee[] staff =  new Employee[ 3 ];  
staff[ 0 ] = new Employee( "harry Hacker" , 35000 );
staff[ 1 ] = new Employee( "carl cracke" , 75000 );
staff[ 2 ] = new Employee( "tony Tester" , 38000 );
Arrays.sort(staff); //sort方法可以实现对对象数组排序,但是必须实现 Comparable接口
class Employee implements Comparable<Employee>  
{
public Employee(String n, double s)
{
name = n;
salary = s;
Random ID = new Random();
id = ID.nextInt( 10000000 );
}
public int getId()
{
return id;
}
public int compareTo(Employee other)
{
if (id<other.id) //这里比较的是什么 sort方法实现的就是按照此比较的东西从小到大排列
return - 1 ;
if (id>other.id)
return 1 ;
return 0 ;
}
private int id;
private String name;
private double salary;
}

Comparator接口

Comparator位于包java.util下,而Comparable位于包java.lang下,Comparable接口将比较代码嵌入自身类中,而后者在一个独立的类中实现比较。 如果类的设计师没有考虑到Compare的问题而没有实现Comparable接口,可以通过  Comparator来实现比较算法进行排序,并且为了使用不同的排序标准做准备,比如:升序、降序。

import java.util.TreeSet; 
import java.util.Comparator;
class NumComparator implements Comparator<NameTag> {
public int compare (NameTag left,NameTag right) {
return(left.getNumber() - right.getNumber());
}
}
public class CollectionNine {
public static void main(String arg[]) {
new CollectionNine();
}
CollectionNine() {
NumComparator comparator = new NumComparator();
TreeSet<NameTag> set = new TreeSet<NameTag>(comparator);
set.add(new NameTag("Agamemnon",300));
set.add(new NameTag("Cato",400));
set.add(new NameTag("Plato",100));
set.add(new NameTag("Zeno",200));
set.add(new NameTag("Archimedes",500));
for(NameTag tag : set)
System.out.println(tag);
}
}

我们遇到的情况就不是如此简单了。如给公司里的商品进行排序,我们很轻易的想到按照商品的名称排序不就完了,而且简单明了。但现实并如我们相信般简单。同一商品名称可以有不同的批次,进货时间,可能还会有单价的不同。显然只根据商品名称排序是不合理的。 

再举个简单例子然后用程序实现。如公司要将员工进行排序(不要说领导排在前面),假设我们的需求比较复杂。先进行姓排序,谁的姓拼音靠前,谁就排前面。然后对名字进行排序。恩.如果同名,女性排前头。如果名字和性别都相同,年龄小的排前头。ok,一个也不算复杂的需求。 

如果对java比较熟悉的会知道java.util.Comparator 接口。要实现里面的函数 
int compare(Object o1, Object o2) 返回一个基本类型的整型,返回负数表示o1 小于o2,返回0 表示o1和o2相等,返回正数表示o1大于o2。 

于是我们设计的人员类要有几个变量,firstname,lastname,sex,age分别表示姓,名,性别,年龄。 

public class Person {  
String firstname,lastname;
Boolean sex;
Integer age;
public Person(String firstname,String lastname,Boolean sex,Integer age) {
this.firstname = firstname;
this.lastname = lastname;
this.sex = sex;
this.age = age;
}
}
public class Comparators {  
public static java.util.Comparator getComparator() {
return new java.util.Comparator() {

public int compare(Object o1, Object o2) {
if (o1 instanceof String) {
return compare( (String) o1, (String) o2);
}else if (o1 instanceof Integer) {
return compare( (Integer) o1, (Integer) o2);
}else if (o1 instanceof Person) {
return compare( (Person) o1, (Person) o2);
}else {
System.err.println("未找到合适的比较器");
return 1;

}
}

public int compare(String o1, String o2) {
String s1 = (String) o1;
String s2 = (String) o2;
int len1 = s1.length();
int len2 = s2.length();
int n = Math.min(len1, len2);
char v1[] = s1.toCharArray();
char v2[] = s2.toCharArray();
int pos = 0;

while (n-- != 0) {
char c1 = v1[pos];
char c2 = v2[pos];
if (c1 != c2) {
return c1 - c2;
}
pos++;
}
return len1 - len2;
}

public int compare(Integer o1, Integer o2) {
int val1 = o1.intValue();
int val2 = o2.intValue();
return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1));

}
public int compare(Boolean o1, Boolean o2) {
return (o1.equals(o2)? 0 : (o1.booleanValue()==true?1:-1));
}

public int compare(Person o1, Person o2) {
String firstname1 = o1.getFirstName();
String firstname2 = o2.getFirstName();
String lastname1 = o1.getLastName();
String lastname2 = o2.getLastName();
Boolean sex1 = o1.getSex();
Boolean sex2 = o2.getSex();
Integer age1 = o1.getAge();
Integer age2 = o2.getAge();
return (compare(firstname1, firstname2) == 0 ?
(compare(lastname1, lastname2) == 0 ? (compare(sex1, sex2) == 0 ? (compare(age1, age2) == 0 ? 0 :
compare(age1, age2)) :
compare(sex1, sex2)) :
compare(lastname1, lastname2)) :
compare(firstname1, firstname2));
}

};
}

}

o1和o2相等返回0,否则o1如果是true 就表示o1大于o2。 

public int compare(Boolean o1, Boolean o2) {  

return (o1.equals(o2)? 0 : (o1.booleanValue()==true?1:-1));
public static void main(String[] args) {  
Person[] person = new Person[] {
new Person("ouyang", "feng", Boolean.TRUE, new Integer(27)),
new Person("zhuang", "gw", Boolean.TRUE, new Integer(27)),
new Person("zhuang", "gw", Boolean.FALSE, new Integer(27)),
new text.Person("zhuang", "gw", Boolean.FALSE, new Integer(2)),
};
for (int i = 0; i < person.length; i++) {
System.out.println("before sort=" + person[i]);
}
java.util.Arrays.sort(person, Comparators.getComparator());

for (int i = 0; i < person.length; i++) {
System.out.println("after sort=" + person[i]);
}
}

java8的Comparators进行集合分组排序

public class Employee implements Comparable<Employee> {

private Integer id = -1;
private Integer age = -1;
private String firstName = null;
private String lastName = null;
}

多个比较器用于字段的名字,姓氏和年龄。

import java.util.Comparator;

public class FirstNameSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getFirstName().compareTo(o2.getFirstName());
}
}

public class LastNameSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getLastName().compareTo(o2.getLastName());
}
}

public class AgeSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getAge() - o2.getAge();
}
}

 Comparator.thenComparing()

使用内置的比较器链接支持,在Java 8中对列表进行排序非常容易。您通过实现​​Comparator​​​接口创建了独立的字段排序器,并将它们链接到​​Collection.sort()​​方法中。

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));

Collections.sort(list, new FirstNameSorter()
.thenComparing(new LastNameSorter())
.thenComparing(new AgeSorter()));

System.out.println(list);
}
}
[Employee [id=1, age=34, firstName=A, lastName=B], 
Employee [id=3, age=31, firstName=B, lastName=A],
Employee [id=4, age=30, firstName=C, lastName=D],
Employee [id=2, age=25, firstName=D, lastName=C]]

CompareToBuilder

值按照它们附加到构建器的顺序进行比较。如果任何比较返回非零结果,则该值将是返回的结果,​​CompareToBuilder.toComparison()​​并且将跳过所有后续比较。

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>

修改模型中的compareTo()方法

import org.apache.commons.lang3.builder.CompareToBuilder;

public class Employee implements Comparable<Employee> {

private Integer id = -1;
private Integer age = -1;
private String firstName = null;
private String lastName = null;

public Employee(Integer id, String fName, String lName, Integer age) {
this.id = id;
this.firstName = fName;
this.lastName = lName;
this.age = age;
}

public int compareTo(Employee o) {

if (o == null) {
return -1;
}

CompareToBuilder buider = new CompareToBuilder();

return buider
.append(this.getFirstName(), o.getFirstName())
.append(this.getLastName(), o.getLastName())
.append(this.getAge(), o.getAge())
.toComparison();
}

//getters and setters
}

排序列表

ublic class MultipleFieldSorter
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
List<Employee> list = //list of employees;

Collections.sort(list);

System.out.println(list);
}
}

CompareToBuilder与比较器接口

如果您不愿意修改​​Comparable​​​界面,您仍然可以利用​​Comparator​​界面对列表CompareToBuilder​进行排序

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.lang3.builder.CompareToBuilder;

public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));

Collections.sort(list, new Comparator<Employee>()
{
public int compare(Employee empOne, Employee empTwo)
{
return new CompareToBuilder()
.append(empOne.getFirstName(), empTwo.getFirstName())
.append(empOne.getLastName(), empTwo.getLastName())
.append(empOne.getAge(), empTwo.getAge())
.toComparison();
}
});

System.out.println(list); //Sorted list
}
}

ComparisonChain

与Apache Common lang类似​​CompareToBuilder​​​,Google guava库提供了有用的类​ComparisonChain来排序对象列表

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>

比较链示例

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.google.common.collect.ComparisonChain;

public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));

Collections.sort(list, new Comparator<Employee>()
{
public int compare(Employee empOne, Employee empTwo)
{
return ComparisonChain.start()
.compare(empOne.getFirstName(), empTwo.getFirstName())
.compare(empOne.getLastName(), empTwo.getLastName())
.compare(empOne.getAge(), empTwo.getAge())
.result();
}
});

System.out.println(list);
}
}

链式比较器

这是使用多个比较器按多个字段对列表对象进行排序的最基本示例。在这种方法中,创建比较器有序列表并将其传递给迭代比较器并使用每个比较器对当前列表进行排序的方法。

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class GroupBySorter implements Comparator<Employee> {

private List<Comparator<Employee>> listComparators;

public GroupBySorter(Comparator<Employee>... comparators) {
this.listComparators = Arrays.asList(comparators);
}

public int compare(Employee empOne, Employee empTwo) {
for (Comparator<Employee> comparator : listComparators) {
int result = comparator.compare(empOne, empTwo);
if (result != 0) {
return result;
}
}
return 0;
}
}

在列表中按排序应用组

现在我们可以使用上面的​​GroupBySorter​​方法对员工列表进行排序。下面的代码按以下顺序对员工列表进行排序:

  • 名字
  • 年龄
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MultipleFieldSorter
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(
new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));

Collections.sort(list, new GroupBySorter(new FirstNameSorter(), new LastNameSorter(), new AgeSorter()));

System.out.println(list);
}
}

 

java源码

Modifier and Type

Method and Description

​int​

​compare(T o1, T​

比较其两个参数的顺序。

​static <T,U extends Comparable<? super U>>
Comparator<T>​

​comparing(Function<? super T,? extends U> keyExtractor)​

接受从类型​​T​​中提取​​Comparable​​排序键的功能,并返回按该排序键进行比较的​​Comparator<T>​​ 。

​static <T,U> Comparator<T>​

​comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)​

接受提取从一个类型排序键的功能​​T​​​ ,并返回一个​​Comparator<T>​​ ,通过使用指定的排序关键字进行比较​​Comparator​​ 。

​static <T> Comparator<T>​

​comparingDouble(ToDoubleFunction<? super T> keyExtractor)​

接受从类型 ​​T​​​中提取 ​​double​​​排序键的功能,并返回一个 ​​Comparator<T>​​ ,该数据按该排序键进行比较。

​static <T> Comparator<T>​

​comparingInt(ToIntFunction<? super T> keyExtractor)​

接受从类型 ​​T​​​中提取 ​​int​​​排序键的功能,并返回与该排序键进行比较的 ​​Comparator<T>​​ 。

​static <T> Comparator<T>​

​comparingLong(ToLongFunction<? super T> keyExtractor)​

接受提取功能 ​​long​​​从类型排序键 ​​T​​​ ,并返回一个 ​​Comparator<T>​​通过那种关键的。

​boolean​

​equals(Object​

指示某个其他对象是否等于此比较器。

​static <T extends Comparable<? super T>>
Comparator<T>​

​naturalOrder()​

返回一个以自然顺序比较​​Comparable​​对象的比较​​器​​ 。

​static <T> Comparator<T>​

​nullsFirst(Comparator<? super T> comparator)​

返回一个空友好的比较是认为 ​​null​​小于非空。

​static <T> Comparator<T>​

​nullsLast(Comparator<? super T> comparator)​

返回一个比较容易的比较器,它将 ​​null​​设置为大于非空值。

​default Comparator<T>​

​reversed()​

返回一个比较器,强制该比较器的相反顺序。

​static <T extends Comparable<? super T>>
Comparator<T>​

​reverseOrder()​

返回一个与 自然排序相反的比较器。

​default Comparator<T>​

​thenComparing(Comparator<? super T> other)​

用另一个比较器返回一个字典顺序比较器。

​default <U extends Comparable<? super U>>
Comparator<T>​

​thenComparing(Function<? super T,? extends U> keyExtractor)​

返回具有提取 ​​Comparable​​​排序键的功能的 ​​Comparable​​顺序比较器。

​default <U> Comparator<T>​

​thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)​

返回具有提取要与给定 ​​Comparator​​​进行比较的键的功能的字典顺序比较 ​​Comparator​​ 。

​default Comparator<T>​

​thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)​

返回具有提取 ​​double​​​排序键的功能的 ​​double​​顺序比较器。

​default Comparator<T>​

​thenComparingInt(ToIntFunction<? super T> keyExtractor)​

返回具有提取 ​​int​​​排序键的功能的 ​​int​​顺序比较器。

​default Comparator<T>​

​thenComparingLong(ToLongFunction<? super T> keyExtractor)​

返回具有提取 ​​long​​​排序键的功能的 ​​long​​顺序比较器。

package java.lang;
import java.util.*;

public interface Comparable<T> {
public int compareTo(T o);
}
package java.util;

import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;

@FunctionalInterface
public interface Comparator<T> {

int compare(T o1, T o2);

boolean equals(Object obj);

default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}

default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}

default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}

default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}

default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}

default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}

default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}

public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}

@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}

public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}

public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}

public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}

public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}

public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
package java.util;

import java.io.Serializable;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

class Comparators {
private Comparators() {
throw new AssertionError("no instances");
}

enum NaturalOrderComparator implements Comparator<Comparable<Object>> {
INSTANCE;

@Override
public int compare(Comparable<Object> c1, Comparable<Object> c2) {
return c1.compareTo(c2);
}

@Override
public Comparator<Comparable<Object>> reversed() {
return Comparator.reverseOrder();
}
}

final static class NullComparator<T> implements Comparator<T>, Serializable {
private static final long serialVersionUID = -7569533591570686392L;
private final boolean nullFirst;
// if null, non-null Ts are considered equal
private final Comparator<T> real;

@SuppressWarnings("unchecked")
NullComparator(boolean nullFirst, Comparator<? super T> real) {
this.nullFirst = nullFirst;
this.real = (Comparator<T>) real;
}

@Override
public int compare(T a, T b) {
if (a == null) {
return (b == null) ? 0 : (nullFirst ? -1 : 1);
} else if (b == null) {
return nullFirst ? 1: -1;
} else {
return (real == null) ? 0 : real.compare(a, b);
}
}

@Override
public Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return new NullComparator<>(nullFirst, real == null ? other : real.thenComparing(other));
}

@Override
public Comparator<T> reversed() {
return new NullComparator<>(!nullFirst, real == null ? null : real.reversed());
}
}
}