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

深入学习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 TypeMethod and Description
intcompare(T o1, T o2)

比较其两个参数的顺序。

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>通过那种关键的。

booleanequals(Object obj)

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

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());
        }
    }
}

 

 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wespten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值