深入学习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
{
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 (idother.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 {
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 set = new TreeSet(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 {
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
{
public int compare(Employee o1, Employee o2)
{
return o1.getFirstName().compareTo(o2.getFirstName());
}
}
public class LastNameSorter implements Comparator
{
public int compare(Employee o1, Employee o2)
{
return o1.getLastName().compareTo(o2.getLastName());
}
}
public class AgeSorter implements Comparator
{
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 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()
并且将跳过所有后续比较。
org.apache.commons
commons-lang3
3.7
修改模型中的compareTo()方法
import org.apache.commons.lang3.builder.CompareToBuilder;
public class Employee implements Comparable {
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 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 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()
{
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
来排序对象列表。
com.google.guava
guava
23.0
比较链示例
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 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()
{
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 {
private List listComparators;
public GroupBySorter(Comparator... comparators) {
this.listComparators = Arrays.asList(comparators);
}
public int compare(Employee empOne, Employee empTwo) {
for (Comparator 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 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 Descriptionint
compare(T o1, T o2)
比较其两个参数的顺序。
static
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?