zoukankan      html  css  js  c++  java
  • Java ArrayList中对象的排序 (Comparable VS Comparator)

    我们通常使用Collections.sort()方法来对一个简单的数据列表排序。但是当ArrayList是由自定义对象组成的,就需要使用comparable或者comparator接口了。在使用这两者进行排序之前,先尝试不实现任何接口来进行排序。

    考虑下面的例子——有一个Student类,具有三个属性:name, rollno, age

    public class Student  {
        private String name;
        private int rollno;
        private int age;
        
        /* 有参构造 ...*/   
        /* getter and setter ...*/   
    }

    然后需要一个Student组成的ArrayList:

    import java.util.*;
    public class ArrayListSorting  {
    
         public static void main(String args[]){
           ArrayList<Student> arraylist = new ArrayList<Student>();
           arraylist.add(new Student(223, "Chaitanya", 26));
           arraylist.add(new Student(245, "Rahul", 24));
           arraylist.add(new Student(209, "Ajeet", 32));
    
           Collections.sort(arraylist);
    
           for(Student str: arraylist){
                System.out.println(str);
           }
         }
    }

    这里尝试去调用Collections.sort()方法,但是出错了:

    Exception in thread “main” java.lang.Error: Unresolved compilation problem:
    Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments (ArrayList). The inferred type Student is not a valid substitute for the bounded parameter > at beginnersbook.com.Details.main(Details.java:11)

    原因:对于排序的ArrayList,除非其中元素实现了Comparable或者Comparator接口,否则不能调用Collections.sort方法。

    使用Comparable对ArrayList<Object>进行排序

    我们想要根据age对Student进行排序——实现Comparable接口,重写compareTo方法。

    package beginnersbook.com;
    
    public class Student implements Comparable {
        private String name;
        private int rollno;
        private int age;
    
        /* 有参构造 */
        ...
        //getter and setter methods
        ...
        @Override
        public int compareTo(Student comparestu) {
            int compareAge=((Student)comparestu).getAge();
            /* 正序排列 */
            return this.age-compareAge;
    
            /* 逆序排列 */
            //return compareAge-this.age;
        }
    
        @Override
        public String toString() {
            return "[ rollno=" + rollno + ", name=" + name + ", age=" + age + "]";
        }
    
    }

    现在我们可以正常调用Collections.sort方法了。

    既然Comparable完成了我们的工作,为什么还需要Comparator呢?

    使用Comparable接口我们只能根据一个属性对ArrayList进行排序。为了让排序可以根据多个属性进行,需要使用Comparator。

    使用Comparator对ArrayList<Object>进行排序(多个属性)

    重写Comparatorcompare方法:

    import java.util.Comparator;
    public class Student  {
        private String name;
        private int rollno;
        private int age;
    
        /* 有参构造 */
        ...
        //Getter and setter methods
        ...
        /* 根据name进行排序 */
        public static Comparator<Student> NameComparator = new Comparator<Student>() {
    
        public int compare(Student s1, Student s2) {
           String name1 = s1.getName().toUpperCase();
           String name2 = s2.getName().toUpperCase();
    
           // 正序排列
           return StudentName1.compareTo(StudentName2);
    
           // 逆序排列
           //return StudentName2.compareTo(StudentName1);
        }};
    
        /* 根据rollno进行排序 */
        public static Comparator<Student> StuRollno = new Comparator<Student>() {
    
          public int compare(Student s1, Student s2) {
    
             int rollno1 = s1.getRollno();
             int rollno2 = s2.getRollno();
    
             /* 正序排列 */
             return rollno1-rollno2;
    
             /* 逆序排列 */
             //return rollno2-rollno1;
        }};
        @Override
        public String toString() {
            return "[ rollno=" + rollno + ", name=" + name + ", age=" + age + "]";
        }
    
    }

    这样,我们就既可以用name进行排序,也可以用age进行排序,只需要在有不同的排序需求时,使用不同的Comparator就可以了(e.g. Collections.sort(arraylist, Student.NameComparator))。

    ——以上内容译自Java ArrayList of Object Sort Example (Comparable And Comparator)


    多属性组合排序

    上面对Java的ArrayList自定义排序进行了基本介绍,下面是工作中遇到的一个需求:

    对于一个漏洞,有两个排序依据,首先根据是否修复来排序,其次按照严重程度排序,类似于SQL中的ORDER BY field1, field2,若field1相同,则比较field2

    可以看到,右边的一列是按照未修复,已修复的顺序排列的,而左边也是按照风险程度由高到低排列,但是分别对应了是否修复的顺序。这种排序可以认为也是多属性排序,但是与上边讲到的多属性不同,这种方式是多种属性结合的排序方式,

        public static Comparator<Loopholes> loopholesComparator = new Comparator<Loopholes>() {
            @Override
            public int compare(Loopholes l1, Loopholes l2) {
                Integer riskLevel1 =  l1.getRiskLevel();
                Integer riskLevel2 =  l2.getRiskLevel();
                Integer fixed1 = l1.getFixed();
                Integer fixed2 = l2.getFixed();
                int fixedComp = fixed1.compareTo(fixed2);
                if (fixedComp != 0) {
                    return fixedComp;
                } else {
                    return riskLevel1.compareTo(riskLevel2);
                }
            }
        };

    首先用fixed1与fixed2进行比较,若两者不相等,则直接排序,若两者相等(即compartTo返回0),继续比较风险等级并返回风险等级的排序结果。

  • 相关阅读:
    nethogs命令执行报异常的解决方法
    性能监控
    Linux图形化监控网络流量:speedometer查看流量
    JMeter监控Slave机器是否执行
    安全测试robots
    在ASP.NET MVC4中实现同页面增删改查,无弹出框02,增删改查界面设计
    在ASP.NET MVC4中实现同页面增删改查,无弹出框01,Repository的搭建
    报错:非介入式客户端验证规则中的验证类型名称必须唯一。下列验证类型出现重复
    ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象
    在ASP.NET MVC中使用Knockout实践09,自定义绑定
  • 原文地址:https://www.cnblogs.com/shiyu404/p/6678925.html
Copyright © 2011-2022 走看看