Comparable接口与Comparator接口
1.Comparable(内部排序接口)简介:
若一个类实现了Comparable接口,就意味着“该类支持排序”。既然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过Collections.sort(或Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用做“有序映射TreeMap”中的键或“有序集合TreeSet”中的元素,而不需要指定比较器。
Comparable定义:
Comparable接口仅仅包括一个函数,它的定义如下:
public interface Comparable{
public int compareTo(T o);
}
关于返回值
可以看出CompareTo方法返回一个int值,该值有三种返回值:
1.返回负数:表示当前对象小于比较对象,
2.返回0:表示当前对象等于目标对象,
3.返回正数:表示当前对象大于目标对象。
2.Comparator(外部排序接口)简介:
Comparator是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Coparator接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对垒进行排序。
Comparator定义:
Comparator接口仅仅只包括两个函数,它的定义如下:
public interface Comparator{
int compare(T o1,T o2);
boolean equals(Object obj);
}
int compare(T o1,T o2);是比较o1和o2的大小。返回负数,意味着o1比o2小;返回0,意味着o1等于o2;返回正数,意味着意味着o1比o2。
3.Comparator和Comparable比较
Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
4.说明:
- String已经实现过Comparable;
Integer已经实现过Comparable。 - 对象无法带有顺序,不能使用<,=,>,如何让解决这个问题呢?
两种办法:
2.1自然顺序: 类实现Comaprable接口
使用方式:
p.comapreTo(q);
2.2非自然顺序:定义一个比较器(实现Comaprator类)
使用方式:
Comparator 比较器=new …;
比较器.compare(p,q); - 泛型接口:
3.1 Comaprable<>
class Person implements Comparable
//1.定义了Person类
//2.Person具备自然顺序
//3.Person类的自然顺序是需要和一个Person比较
3.2 Comparator<>
class PersonHeightComparator implements Comparator
//1.定义了一个比较器类,名字是PersonHeightComparator
//2.这个比较器负责Person类型的比较 - 有Comparable为何还要引入Comparator?
有些天生没有自然顺序,或者自然顺序比满足我们的需要,所以需要引入比较器来做比较。
示例1:
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String toString() {
return "Person{" + "name='" + name + '\'' + ",age=" + age + '}';
}
public String getName() {
return name;
}
public void setName() {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge() {
this.age = age;
}
}
class AscAgeComparator implements Comparator<Person> {
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
class DescAgeComparator implements Comparator<Person> {
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
}
public class TestDemo {
public static void main(String[] args) {
Set<Person> set = new TreeSet<>(new AscAgeComparator());
set.add(new Person("张三", 20));
set.add(new Person("李四", 18));
System.out.println(set);
Set<Person> set2 = new TreeSet<>(new DescAgeComparator());
set2.add(new Person("张三", 20));
set2.add(new Person("李四", 18));
System.out.println(set2);
}
}
运行结果:
示例2:
import java.util.Comparator;
class PersonHeightComparator implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
return (int)(o1.height-o2.height);
}
}
class PersonNameComparator implements Comparator<Person>{
@Override
//把Person1的name取出来,并用Person1的自然顺序为比较顺序
public int compare(Person o1, Person o2) {
return o1.name.compareTo(o2.name);
}
}
public class Person implements Comparable<Person>{
public String name;
public int age;
public double height;
public int weight;
public int level;
public int gender;
public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
@Override
public int compareTo(Person o) {
return age-o.age;
/*
if(age<o.age){
return -1;
}else if(age==o.age){
return 0;
}else if(age>o.age){
return 1;
}
*/
}
//设计一个复杂比较器,比较顺序依次为身高、体重、姓名、年龄
class ComplexComparator implements Comparator<Person>{
@Override
public int compare(Person o1, Person o2) {
if(o1.height<o2.height){
return -1;
}else if(o1.height>o2.height){
return 1;
}
if(o1.weight<o2.weight){
return -1;
}else if(o1.weight>o2.weight){
return 1;
}
int n=o1.name.compareTo(o2.name);
if(n!=0){
return n;
}
return o1.age-o2.age;
}
}
public static void main(String[] args) {
Person p=new Person("James",18,185.0);
Person q=new Person("Tom",20,180.2);
//按照年龄比较
System.out.println("按照年龄比较:");
int a=p.compareTo(q);
if(a<0){
System.out.println("p小于q");
}else if(a==0){
System.out.println("p等于q");
}else{
System.out.println("p大于q");
}
Comparator<Person> comparator=new PersonNameComparator();
//按照姓名比较
System.out.println("按照姓名比较:");
int n=comparator.compare(p,q);
if(n<0){
System.out.println("p小于q");
}else if(n==0){
System.out.println("p等于q");
}else{
System.out.println("p大于q");
}
comparator=new PersonHeightComparator();
//基于身高的比较
System.out.println("按照身高比较:");
int h=comparator.compare(p,q);
if(h<0){
System.out.println("p小于q");
}else if(h==0){
System.out.println("p等于q");
}else{
System.out.println("p大于q");
}
//额外的验证用例:String和Integer已经实现过Comparable
System.out.println("额外的验证用例:体现String已经实现过Comparable:");
System.out.println("abc".compareTo("bbc"));
System.out.println("abc".compareTo("abcd"));
}
}
运行结果:
示例3.1:下例的前奏
import java.util.Comparator;
public class Student {
static class Sort{
static void insertSort(Student[] students){
for(int i=1;i<students.length;i++){
Student k=students[i];
int j=i-1;
for(; j>0&&((Comparable<Student>)students[j]).compareTo(k)>0; j--){
students[j+1]=students[j];
}
students[j+1]=k;
}
}
static void insertSort(Student[] students,Comparator<Student> cmp){
for(int i=1;i<students.length;i++){
Student k=students[i];
int j=i-1;
for(; j>0&&cmp.compare(students[j],k)>0; j--){
students[j+1]=students[j];
}
students[j+1]=k;
}
}
}
public String sn;
public String name;
public int age;
public static class Cmp implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return 0;
}
}
public static void main(String[] args) {
Student[] students={new Student()};
Sort.insertSort(students,new Cmp());
}
}
示例3.2:和图书排序有关的联系
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Book implements Comparable<Book>{
String ISBN;
String title;
String author;
int price;
int sales;
int comments;
public Book(String ISBN, String title, String author, int price, int sales, int comments) {
this.ISBN = ISBN;
this.title = title;
this.author = author;
this.price = price;
this.sales = sales;
this.comments = comments;
}
@Override
public int compareTo(Book o) {
return 0;
}
@Override
public String toString() {
return "Book{" +
"ISBN='" + ISBN + '\'' +
", title='" + title + '\'' +
", author='" + author + '\'' +
", price=" + price +
", sales=" + sales +
", comments=" + comments +
'}';
}
static class Sort {
public static void sort(List<Book> books) {
for (int i = 1; i < books.size(); i++) {
Book book = books.get(i);
int j = i - 1;
for (; j >= 0 && books.get(j).compareTo(book) > 0; j--) {
books.set(j + 1, books.get(j));
}
books.set(j + 1, book);
}
}
public static void sort(List<Book> books, Comparator<Book> comparator) {
for (int i = 1; i < books.size(); i++) {
Book book = books.get(i);
int j = i - 1;
for (; j >= 0 && comparator.compare(books.get(j), book) > 0; j--){
books.set(j + 1, books.get(j));
}
books.set(j + 1, book);
}
}
}
static class TitleComparator implements Comparator<Book> {
@Override
public int compare(Book o1, Book o2) {
return o1.title.compareTo(o2.title);
}
}
static class PriceComparator implements Comparator<Book>{
/**
* true代表从小到大,false代表从大到小
*/
boolean asc;
public PriceComparator(boolean asc) {
this.asc = asc;
}
@Override
public int compare(Book o1, Book o2) {
if(asc){
return o1.price-o2.price;
}else{
return o2.price-o1.price;
}
}
}
public static void main(String[] args) {
List<Book> books = new ArrayList<>();
books.add(new Book("9787201151304", "从一到无穷大", "[美] 乔治·伽莫夫", 1600, 400, 26));
books.add(new Book("9787020147465", "应物兄", "李洱", 7900, 1668, 300));
books.add(new Book("9787220107085", "如何写甲骨文", "日本文字文化机构", 8800, 23, 6));
books.add(new Book("9787521706635", "敌人与邻居", "[英]伊恩·布莱克", 10800, 3, 0));
books.add(new Book("9787301280751", "法国大革命 (第2版)", "布兰宁(T.C.W.Blanning)", 4500, 1993, 188));
List<Book> copy;
// 按自然顺序(ISBN)排序
System.out.println("按 ISBN 排序:");
copy = new ArrayList<>(books);
Sort.sort(copy);
System.out.println(copy);
// 按书名排序
System.out.println("按 书名 排序:");
copy = new ArrayList<>(books);
Sort.sort(copy, new TitleComparator());
System.out.println(copy);
// 按价格排序-从小到大
System.out.println("按 价格-从小到大 排序:");
copy = new ArrayList<>(books);
Sort.sort(copy, new PriceComparator(true));
System.out.println(copy);
// 按价格排序-从大到小
System.out.println("按 价格-从大到小 排序:");
copy = new ArrayList<>(books);
Sort.sort(copy, new PriceComparator(false));
System.out.println(copy);
}
}
运行结果: