• Java排序器之升序or降序


    一、如何确定升序还是降序?

    Java中在进行对象排序时,设计的排序器经常会对两个对象按照一定的排序规则排序,可如何确定排序规则是升序还是降序呢?笔者整理了一个简单的方法来确定排序规则。

    o1和o2是需要表示排序的两个对象,假定比较前的默认顺序为 [o1, o2],是升序还是降序暂时不做考虑,完全根据返回值结果表示是否需要调整当前的排序顺序,便能够理解排序的真正逻辑,以确定是升序排序还是降序排序。

    假设我们的比较器规则如下:o1对象作为比较的前者,o2对象作为排序的后者,即比较方式为 [o1 - o2]或者 [o1.compareTo(o2)]。

    class ComparatorByAge implements Comparator {
    
        // 根据年龄和姓名排序
        @Override
        public int compare(Object o1, Object o2) {
            Person p1 = (Person) o1;
            Person p2 = (Person) o2;
    
            int tmp = p1.getAge() - p2.getAge();
            return tmp == 0 ? p1.getName().compareTo(p2.getName()) : tmp;
        }
    }

    升序规则:

    • o1 > o2,返回正数,true,表示需要调整顺序,升序。
    • o1 < o2,返回负数,false,表示不需要调整顺序,升序。
    降序规则:
    • o1 > o2,返回负数,false,表示不需要调整顺序,降序。
    • o1 < o2,返回正数,true,表示需要调整顺序,降序。 
    不排序规则:
    • o1 = o2,返回0,按当前顺序即可,或者比较其他参数。

    二、实际用例

    Person 是定义的需要排序的对象,包括年龄和姓名两个字段。
    class Person implements Comparable{
    
        private String name;
        private int age;
    
        // 重写toString()方法,输出对象时输出格式为:name:age
        @Override
        public String toString() {
            return name+ ":" + age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        // Person自带的排序规则
        @Override
        public int compareTo(Object o) {
            Person p = (Person) o;
    
        // 根据年龄进行排序
          int temp = this.age - p.age;
          return temp == 0 ? this.name.compareTo(p.name):temp;
        }
    }
    View Code

    排序规则一:定义升序排序器,先按年龄升序,再按姓名首字母升序。

    • 比如 o1对象为 (zhangshan:20) ,o2 对象为 (wangwu:21) ,默认排序 [o1, o2],由于 o1.age < o2.age,比较结果返回负数,false,表示不需要调整规则,按年龄升序排序,最终排序结果为 [zhangshan:20, wangwu:21]。
    • 比如 o1 对象为 (zhangshan:20) ,o2对象为 (lisi:20),默认排序 [o1,o2],由于 o1.age = o2.age,比较结果为0,不按年龄排序,进一步比较name,由于 o1.name > o2.name,返回 true,调整排序规则,即按字母升序排序,最终排序结果为 [lisi:20, zhangshan:20]。
    /**
     * 自定义升序排序器
     * 升序:先按年龄升序,再按姓名首字母升序
     */
    class ComparatorByAge implements Comparator {
    
        // 根据年龄排序
        @Override
        public int compare(Object o1, Object o2) {
            Person p1 = (Person) o1;
            Person p2 = (Person) o2;
    
            int tmp = p1.getAge() - p2.getAge();
            return tmp == 0 ? p1.getName().compareTo(p2.getName()) : tmp;
        }
    }

    排序规则二:定义降序排序器,先按年龄降序,再按姓名首字母降序。和升序的唯一区别就是返回结果的参数前添加了一个负号。

    /**
     * 自定义降序排序器
     * 降序:先按年龄降序,再按姓名首字母降序
     */
    class ComparatorByAge2 implements Comparator {
    
        // 根据年龄排序
        @Override
        public int compare(Object o1, Object o2) {
            Person p1 = (Person) o1;
            Person p2 = (Person) o2;
    
            int tmp = p1.getAge() - p2.getAge();
            return tmp == 0 ? -(p1.getName().compareTo(p2.getName())) : -tmp;
        }
    }

    排序 main() 方法,查看两种排序器的排序结果。

    public class TreeSetDemo {
        public static void main(String[] args) {
            TreeSet<Person> ts = new TreeSet(new ComparatorByAge());
            ts.add(new Person("zhangsan", 20));
            ts.add(new Person("wangwu", 21));
            ts.add(new Person("lisi", 20));
            ts.add(new Person("zhouqi", 29));
            ts.add(new Person("zhaoliu", 28));
    
            for (Person person : ts) {
                System.out.println(person);
            }
            /* 结果输出
            lisi:20
            zhangsan:20
            wangwu:21
            zhaoliu:28
            zhouqi:29
            */
    
            ts = new TreeSet(new ComparatorByAge2());
            ts.add(new Person("zhangsan", 20));
            ts.add(new Person("wangwu", 21));
            ts.add(new Person("lisi", 20));
            ts.add(new Person("zhouqi", 29));
            ts.add(new Person("zhaoliu", 28));
            for (Person person : ts) {
                System.out.println(person);
            }
            /* 结果输出
            zhouqi:29
            zhaoliu:28
            wangwu:21
            zhangsan:20
            lisi:20
            */
        }
    }
  • 相关阅读:
    [转]win7 系统装SQLServer2000 成功。
    Windows CE 电源管理(转贴)
    [转]Win7系统下VS2005_2008不识别WinCE5 SDK
    [转]windows 7 下ASP.net 本地配置 ( IIS 7)
    [转]SelectObject() 装载字体 VC EVC
    Mobile Development: Disable Windows Mobile 6.5 Start and Close Button
    [转]WebForm 与 winform 路径获取
    1. chromedriver的下载和配置
    Slf4j打印异常的堆栈信息
    写个日志请求切面,前后端甩锅更方便
  • 原文地址:https://www.cnblogs.com/lemonu/p/13409446.html
Copyright © 2020-2023  润新知