参考链接: Java比较器接口与示例

写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。技术是开源的、知识是共享的。 这博客是对自己学习的一点点总结及记录,如果您对 Java、算法 感兴趣,可以关注我的动态,我们一起学习。  用知识改变命运,让我们的家人过上更好的生活。 

 

 

 比如Integer,double等基本类型数据,Java可以对他们进行比较排序,但是在 Java 中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题 。 

 

 

 

 目录

 一、java中的sort()方法二、自然排序:Comparable1.自然排序的定义2.实现过程3.示例代码

   

   三、定制排序 :Comparator1.实现过程2.示例代码

   

  

 

 

 

一、java中的sort()方法 

 

 在java.util.Collections类中有个sort()方法,主要是用来给数组排序 

 

public class CompareTest1 {

    @Test

    public void test() {

        String[] arr = new String[]{"AA", "SS", "FF", "OO", "EE", "HH"};

        System.out.println("排序之前: " + Arrays.toString(arr));

        Arrays.sort(arr);

        System.out.println("排序之后: " + Arrays.toString(arr));

    }

}

 

代码执行结果: 

排序之前: [AA, SS, FF, OO, EE, HH]

排序之后: [AA, EE, FF, HH, OO, SS]

 

 

 需求:商场有一批水果,对水果的价格进行排序 

 

水果类: 

public class Fruit {

    private String name;

    private double price;

 

    public Fruit() {

    }

 

    public Fruit(String name, double price) {

        this.name = name;

        this.price = price;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public double getPrice() {

        return price;

    }

 

    public void setPrice(double price) {

        this.price = price;

    }

 

    @Override

    public String toString() {

        return "Fruit{" +

                "name='" + name + '\'' +

                ", price=" + price +

                '}';

    }

}

 

 

测试类: 

public class CompareTest2 {

    @Test

    public void test() {

        Fruit[] arr = new Fruit[5];

        arr[0] = new Fruit("apple", 18);

        arr[1] = new Fruit("pear", 6);

        arr[2] = new Fruit("banana", 14);

        arr[3] = new Fruit("watermelon", 26);

        arr[4] = new Fruit("tomato", 6);

        System.out.println("排序之前: " + Arrays.toString(arr));

        // 排序

        Arrays.sort(arr);

        System.out.println("排序之后: " + Arrays.toString(arr));

    }

}

 

程序将会报错: 

java.lang.ClassCastException: xxx.Fruit cannot be cast to java.lang.Comparable

 

 

 报错原因:类型转换错误。 

 

为了解决这个错误,对象之间的排序将用到比较器。 

 

 Java 实现对象排序的方式有两种: 

 自然排序: java.lang.Comparable 

 定制排序: java.util.Comparator 

 

二、自然排序:Comparable 

1.自然排序的定义 

 

 Comparable 接口强行对实现它的每个类的对象进行整体排序 

 

2.实现过程 

 

 实现 Comparable接口的类必须实现 compareTo(Object obj) 方法,两个对象通过 compareTo方法的返回值来比较大小 。 ① 如果当前对象 this 大于形参对象 obj 则返回正整数; ② 如果当前对象 this 小于 形参对象 obj则返回 负整数; ③ 如果当前对象 this 等于 形参对象 obj 则返回零 。 实现 Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort 进行自动排序。 实现此接口的对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器 

 

为了解决类型转换错误,在水果类里面实现Comparable接口。 

3.示例代码 

水果类: 

public class Fruit implements Comparable<Fruit> {

    private String name;

    private double price;

 

    public Fruit() {

    }

 

    public Fruit(String name, double price) {

        this.name = name;

        this.price = price;

    }

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public double getPrice() {

        return price;

    }

 

    public void setPrice(double price) {

        this.price = price;

    }

 

    @Override

    public String toString() {

        return "Fruit{" +

                "name='" + name + '\'' +

                ", price=" + price +

                '}';

    }

 

    // 水果价格从低到高进行排序,若价格相同则按水果名称从高到低排序

    @Override

    public int compareTo(Fruit fruit) {

        if (this.price > fruit.price) {

            return 1;

        } else if (this.price < fruit.price) {

            return -1;

        } else {

            // this.name.compareTo(fruit.name) 按名称从低到高,前面加负号,表示相反

            return -this.name.compareTo(fruit.name);

        }

    }

}

 

注:测试类代码同Test2 代码执行结果: 

排序之前: [Fruit{name='apple', price=18.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='tomato', price=6.0}]

排序之后: [Fruit{name='tomato', price=6.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='apple', price=18.0}, Fruit{name='watermelon', price=26.0}]

 

三、定制排序 :Comparator 

 

 在实际开发中,遇到当元素的类型实现了Comparable 接口,但是它的排序方式不适合当前的操作;或者根本没有实现Comparable 接口,而又不方便修改代码。那么可以考虑使用 Comparator 的对象进行排序。 

 

1.实现过程 

 

 定义一个比较器对象; 重写 compare(Object o1,Object o2) 方法,比较 o1 和 o2 的大小: ① 如果方法返回正整数,则表示 o1 大于 o2 ; ② 如果方法返回 0 ,表示相等; ③ 如果方法返回负整数,表示o1 小于 o2 。 

 可以 将 Comparator 传递给 sort 方法,从而允许在排序顺序上实现精确控制 。 

 

2.示例代码 

public class CompareTest3 {

    /**

     * 按字符从大到小进行排序

     */

    @Test

    public void test() {

        String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "FF", "DD"};

        System.out.println("原来的字符串: " + Arrays.toString(arr));

        Arrays.sort(arr, new Comparator<String>() {

            @Override

            public int compare(String o1, String o2) {

                return -o1.compareTo(o2);

            }

        });

        System.out.println("按字符从大到小排序后的字符串: " + Arrays.toString(arr));

    }

}

 

 

代码执行结果: 

原来的字符串: [AA, CC, KK, MM, GG, FF, DD]

按字符从大到小排序后的字符串: [MM, KK, GG, FF, DD, CC, AA]

 

 

 对水果的价格进行排序 

 

注:水果类同前,节省篇幅,在此不再重复。 

public class CompareTest4 {

    @Test

    public void test() {

        Fruit[] arr = new Fruit[5];

        arr[0] = new Fruit("apple", 18);

        arr[1] = new Fruit("pear", 6);

        arr[2] = new Fruit("banana", 14);

        arr[3] = new Fruit("watermelon", 26);

        arr[4] = new Fruit("watermelon", 6);

        System.out.println("排序之前: " + Arrays.toString(arr));

 

        Arrays.sort(arr, new Comparator<Fruit>() {

            // 按照水果名称从低到高排序,若名称相同则按照价格从高到低排序

            @Override

            public int compare(Fruit o1, Fruit o2) {

                if (o1.getName().equals(o2.getName())) {

                    return -Double.compare(o1.getPrice(), o2.getPrice());

                } else {

                    return o1.getName().compareTo(o2.getName());

                }

            }

        });

        System.out.println("排序之后: " + Arrays.toString(arr));

    }

}

 

 

代码执行结果: 

排序之前: [Fruit{name='apple', price=18.0}, Fruit{name='pear', price=6.0}, Fruit{name='banana', price=14.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='watermelon', price=6.0}]

排序之后: [Fruit{name='apple', price=18.0}, Fruit{name='banana', price=14.0}, Fruit{name='pear', price=6.0}, Fruit{name='watermelon', price=26.0}, Fruit{name='watermelon', price=6.0}]

 

 

 

 当定制排序和自然排序同时存在时,最终的排序结果是按照定制排序进行排序的。 

 

上一篇 聊聊 StringBuffer 与 StringBuilder

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐