博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
猿来绘Java-40-比较器(Comparable 接口与 CompareTo方法)
阅读量:2094 次
发布时间:2019-04-29

本文共 5848 字,大约阅读时间需要 19 分钟。

如何实现普通对象的排序,比如按某个属性的大小比较?

如何实现普通对象(自定义类的对象)的排序,比如按某个属性的大小比较?

Java中的对象,正常情况下,只能进行比较:== 或 != (== 操作是比较的对象的引用地址是否相同,如果使用equals方法,Object类中有equals方法内部就是使用了==,自定义类可以重写equals方法)。不能使用 > 或 < 的但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。

如何实现?Java中提供了两个接口: Comparable 或 Comparator

 

 

Comparable接口的使用举例: 自然排序

1.Java中的String类、包装类(Integer、Double、Short)等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。重写了compareTo()方法以后,就可以从小到大的排列

2. 重写compareTo(obj)的规则:

如果当前对象this大于形参对象obj,则返回正整数,

如果当前对象this小于形参对象obj,则返回负整数,

如果当前对象this等于形参对象obj,则返回零。

3. 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序

 

由于String类实现了Comparable接口,实现了compareTo方法,所以可对String对象进行排序

 

//StringArray.javapackage com.ylaihui.comparable;import org.junit.Test;import java.util.Arrays;public class StringArray {    @Test    public void test1(){        String[] strs = new String[]{"yy","ll","aa","ii","hh","uu","ii"};        Arrays.sort(strs);        System.out.println(Arrays.toString(strs));  // [aa, hh, ii, ii, ll, uu, yy]    }}

自定义类对象排序报异常ClassCastException

 

通过之前对sort方法的分析,我们发现,要排序某个自定义类的对象,需要用到compareTo方法,该方法是在Comparable接口中的,所以要想实现自定义类的对象的排序,需要实现Comparable接口中的compareTo方法,否则会报 ClassCastException异常。

 

//Person.javapackage com.ylaihui.comparable;public class Person {    String name;    int age;    public Person() {    }    public Person(String name, int age) {        this.name = name;        this.age = age;    }    @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }}
//PersonSort.javapackage com.ylaihui.comparable;import java.util.Arrays;public class PersonSort {    public static void main(String[] args) {        Person[] people = new Person[4];        people[0] = new Person("yy",22);        people[1] = new Person("ll",23);        people[2] = new Person("aa",24);        people[3] = new Person("ii",25);        // ClassCastException: com.ylaihui.comparable.Person cannot be cast to java.lang.Comparable        Arrays.sort(people);        System.out.println(people);    }}

自定义类对象的排序-自然排序

 

对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序

//Animal.javapackage com.ylaihui.comparable;public class Animal implements Comparable{    String name;    int age;    public Animal(String name, int age) {        this.name = name;        this.age = age;    }    public Animal() {    }    @Override    public String toString() {        return "Animal{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    }    @Override    public int compareTo(Object o) {        if(o instanceof Animal){            Animal animal = (Animal)o;            if(this.age > animal.age)                return 1;            else if(this.age < animal.age)                return -1;            else                return 0;        }else            throw new RuntimeException("类型不一致,无法比较");    }}
//AnimalSort.javapackage com.ylaihui.comparable;import java.util.Arrays;public class AnimalSort {    public static void main(String[] args) {        Animal[] animals= new Animal[4];        animals[0] = new Animal("yy",22);        animals[1] = new Animal("ll",23);        animals[2] = new Animal("aa",24);        animals[3] = new Animal("ii",25);        Arrays.sort(animals);        System.out.println("sort by age");        System.out.println(Arrays.toString(animals));    }}

定制排序Comparator接口

当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序

 

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

 

//ComparatorTest.javapackage com.ylaihui.comparable;import java.util.Arrays;import java.util.Comparator;public class ComparatorTest {    public static void main(String[] args) {        Animal[] animals= new Animal[6];        animals[0] = new Animal("yy",22);        animals[1] = new Animal("ll",23);        animals[2] = new Animal("aa",24);        animals[3] = new Animal("aa",27);        animals[4] = new Animal("ii",28);        animals[5] = new Animal("hh",28);        // 创建了一个匿名子类的匿名对象         Arrays.sort(animals, new Comparator() {            @Override            // 按 age 从大到小排序            public int compare(Object o1, Object o2) {                if(o1 instanceof Animal && o2 instanceof Animal){                    Animal a1 = (Animal) o1;                    Animal a2 = (Animal) o2;                    return -(a1.age - a2.age);                }else                    throw new RuntimeException("类型不一致,无法比较");            }        });        System.out.println(Arrays.toString(animals));    }}

 

 

//ComparatorTest1.javapackage com.ylaihui.comparable;import java.util.Arrays;import java.util.Comparator;public class ComparatorTest1 {    public static void main(String[] args) {        Animal[] animals= new Animal[6];        animals[0] = new Animal("yy",23);        animals[1] = new Animal("ll",23);        animals[2] = new Animal("aa",24);        animals[3] = new Animal("aa",27);        animals[4] = new Animal("ii",28);        animals[5] = new Animal("hh",28);        Arrays.sort(animals, new Comparator() {            @Override            // 按 age 从大到小排序,age相同,按name从大到小排序            public int compare(Object o1, Object o2) {                if(o1 instanceof Animal && o2 instanceof Animal){                    Animal a1 = (Animal) o1;                    Animal a2 = (Animal) o2;                    if(a1.age == a2.age)                        return -a1.name.compareTo(a2.name);                    return -(a1.age - a2.age);                }else                    throw new RuntimeException("类型不一致,无法比较");            }        });        System.out.println(Arrays.toString(animals));    }}

Comparable接口与Comparator的区别

 

Comparable接口的方式一旦确定,保证Comparable接口实现类的对象在任何位置都可以比较大小,可多次使用。自然排序

Comparator接口属于临时性的比较,只能使用一次。定制排序

 

转载地址:http://rtuhf.baihongyu.com/

你可能感兴趣的文章
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
(PAT 1019) General Palindromic Number (进制转换)
查看>>
(PAT 1073) Scientific Notation (字符串模拟题)
查看>>
(PAT 1080) Graduate Admission (排序)
查看>>
Play on Words UVA - 10129 (欧拉路径)
查看>>
mininet+floodlight搭建sdn环境并创建简答topo
查看>>
【linux】nohup和&的作用
查看>>
Set、WeakSet、Map以及WeakMap结构基本知识点
查看>>
【NLP学习笔记】(一)Gensim基本使用方法
查看>>
【NLP学习笔记】(二)gensim使用之Topics and Transformations
查看>>
【深度学习】LSTM的架构及公式
查看>>
【python】re模块常用方法
查看>>
剑指offer 19.二叉树的镜像
查看>>
剑指offer 20.顺时针打印矩阵
查看>>
剑指offer 23.从上往下打印二叉树
查看>>
Leetcode C++《热题 Hot 100-18》538.把二叉搜索树转换为累加树
查看>>
Leetcode C++《热题 Hot 100-21》581.最短无序连续子数组
查看>>