猿来绘Java-40-比较器(Comparable 接口与 CompareTo方法)

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

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

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.java
package 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.java
package 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.java
package 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.java
package 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.java
package 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.java
package 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.java
package 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接口属于临时性的比较,只能使用一次。定制排序

猜你喜欢

转载自blog.csdn.net/asdfjklingok/article/details/118082317
今日推荐