Java中的排序接口Comparable和比较器Comparator详解
在java中经常涉及到对象数组的比较的情况,常见的有两种方法来处理:
- 自然排序: 继承comparable接口,并实现compareTo()方法
- 定制排序: 定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法
一、Comparable
1.1、Comparable简介
Comparable 是排序接口。(自然排序)
若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
1.2、Comparable 的典型实现:(默认都是从小到大排列的)
1)String:按照字符串中字符的Unicode值进行比较
2)Character:按照字符的Unicode值来进行比较
3)数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
4)Boolean:true 对应的包装类实例大于 false 对应的包装类实例
5)Date、Time等:后面的日期时间比前面的日期时间大
1.3、Comparable 定义
Comparable 接口仅仅只包括一个函数,它的定义如下:
package java.lang;
import java.util.*;public interface Comparable {public int compareTo(T o);
}
解释: 假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
这里为了大家更好的理解Compareable这个接口, 我自己手写了一个Compareable接口.
案例1
Comparable接口
package com.company.strategy2;/*** Created by 苍狼* Time on 2022-08-06*/
public interface Comparable {public int compareTo(T object);}
Cat实体类
package com.company.strategy2;/*** Created by 苍狼* Time on 2022-08-06*/
public class Cat implements Comparable {private int height;private int weight;public Cat(int height, int weight){this.height = height;this.weight = weight;}public int compareTo(Cat cat){if(this.height>cat.height){return 1;} else if(this.heightpackage com.company.strategy2;/*** Created by 苍狼* Time on 2022-08-06*/
public class Sorter {public static void sort(Comparable[] arr) {if (arr == null || arr.length < 2) {return;}for (int e = arr.length - 1; e > 0; e--) {for (int i = 0; i < e; i++) {if (arr[i].compareTo(arr[i + 1]) == 1) {swap(arr, i, i + 1);}}}}public static void swap(Comparable[] arr, int i, int j) {Comparable temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}
测试类
package com.company.strategy2;import java.util.Arrays;public class Main {public static void main(String[] args) {Cat[] cats = {new Cat(111,111), new Cat(555,555), new Cat(222,222), new Cat(444,444)};Sorter sorter = new Sorter();sorter.sort(cats);System.out.println(Arrays.toString(cats));}
}
实际使用中则不需要自己手写Comparable接口和sort排序算法.
案例2:
Pig实体类
package com.company.strategy2;/*** Created by 苍狼* Time on 2022-08-07*/
public class Pig implements java.lang.Comparable {private Double weight;public Pig(Double weight){this.weight = weight;}@Overridepublic int compareTo(Pig pig) {if (this.weight>pig.weight) {return 1;} else if (this.weight
测试类
package com.company.strategy2;import java.util.Arrays;/*** Created by 苍狼* Time on 2022-08-07*/
public class Test {public static void main(String[] args) {Pig[] pigs = new Pig[]{new Pig(123.5), new Pig(145.6), new Pig(111.6)};System.out.println(Arrays.toString(pigs));Arrays.sort(pigs);System.out.println(Arrays.toString(pigs));}
}
运行结果

二、Comparator
2.1、Comparator简介
1) 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排序的比较。
2) 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
3) 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
4) 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
2.2、Comparator定义
Comparator 接口仅仅只包括两个个函数,它的定义如下:
package java.util;public interface Comparator {int compare(T o1, T o2);boolean equals(Object obj);
}
解释: 若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
问题: 为什么可以不实现 equals(Object obj) 函数呢?
因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”
同样的, 为了大家更加直观的理解, 我这里也同样写两个案例, 一个手写Comparator接口, 一个使用java提供的Comparator接口
案例1:
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/@FunctionalInterface //如果这里只有一个方法, 则这个也可以不写
public interface Comparator {public int compare(T t1, T t2);default void show(){System.out.println("世界, 你好....");}}
Cat实体类
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/
public class Cat{private int height;private int weight;public Cat(int height, int weight){this.height = height;this.weight = weight;}@Overridepublic String toString() {return "Cat{" +"height=" + height +", weight=" + weight +'}';}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}
}
cat的比较器类
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/
public class CatComparator implements Comparator{@Overridepublic int compare(Cat t1, Cat t2) {if(t1.getHeight()*t1.getWeight()>t2.getHeight()*t2.getWeight()){return 1;} else if (t1.getHeight()*t1.getWeight()
排序类Sorter中的sort排序方法
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/
public class Sorter {public void sort(T[] arr, Comparator comparator) {if (arr == null || arr.length < 2) {return;}for (int e = arr.length - 1; e > 0; e--) {for (int i = 0; i < e; i++) {if (comparator.compare(arr[i], arr[i+1])==1){swap(arr, i, i+1);}}}}public void swap(T[] arr, int i, int j) {T temp = arr[i];arr[i] = arr[j];arr[j] = temp;}
}
测试类
package com.company.strategy3;import java.util.Arrays;public class Main {public static void main(String[] args) {Cat[] cats = {new Cat(111,111), new Cat(555,555), new Cat(222,222), new Cat(444,444)};Sorter sorter1 = new Sorter<>();sorter1.sort(cats, new CatComparator());System.out.println(Arrays.toString(cats));}
}
这里也可以用测试类Lambda表达式来写
package com.company.strategy3;import java.util.Arrays;public class Main {public static void main(String[] args) {Sorter sorter = new Sorter();Cat[] cats= new Cat[]{new Cat(1111,1111), new Cat(8888,8888), new Cat(3333,3333), new Cat(6666,6666)};sorter.sort(cats, (o1,o2)->{if (o1.getHeight()>o2.getHeight()){return 1;} else if (o1.getHeight()
案例2:
Dog实体类
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/
public class Dog implements Comparable {private int food;public Dog(int food){this.food = food;}@Overridepublic int compareTo(Dog dog) {if(this.food > dog.food){return 1;} else if (this.food < dog.food){return -1;} else{return 0;}}@Overridepublic String toString() {return "Dog{" +"food=" + food +'}';}public void setFood(int food){this.food = food;}public int getFood(){return this.food;}
}
Dog的比较器类
package com.company.strategy3;/*** Created by 苍狼* Time on 2022-08-06*/
public class DogComparator implements Comparator{@Overridepublic int compare(Dog t1, Dog t2) {if (t1.getFood()>t2.getFood()){return 1;} else if (t1.getFood()
测试类
package com.company.strategy3;import java.util.Arrays;/*** Created by 苍狼* Time on 2022-08-07*/
public class Test {public static void main(String[] args) {Dog[] dogs = new Dog[]{new Dog(111), new Dog(777), new Dog(555), new Dog(333)};System.out.println(Arrays.toString(dogs));System.out.println("=====================");Arrays.sort(dogs, new DogComparator());System.out.println(Arrays.toString(dogs));}
}
运行结果

三、Comparator 和 Comparable比较
Comparable是排序接口: 若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器: 我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
