【问题标题】:Sorting a list in Java using 2 criteria使用 2 个标准在 Java 中对列表进行排序
【发布时间】:2021-03-18 14:44:15
【问题描述】:

我有一个对象列表。每个对象都包含一个String 和一个Date(等等)。

我想先按String 排序,然后再按Date

如何以最干净的方式完成这项工作?

谢谢!

Krt_马耳他

【问题讨论】:

    标签: java sorting


    【解决方案1】:

    使用 Java 8,这真的很容易。给定

    class MyClass {
        String getString() { ... }
        Date getDate() { ... }
    }
    

    您可以轻松地对列表进行如下排序:

    List<MyClass> list = ...
    list.sort(Comparator.comparing(MyClass::getString).thenComparing(MyClass::getDate));
    

    【讨论】:

      【解决方案2】:

      给定一个如下所示的对象类:

      public class MyObject {
          public String getString() { ... }
          public Date getDate() { ... }
          ...
      }
      

      像这样编写一个自定义比较器类:

      public class ObjectComparator implements Comparator{
      
          public int compare(Object obj1, Object obj2) {
              MyObject myObj1 = (MyObject)obj1;
              MyObject myObj2 = (MyObject)obj2;
              stringResult = myObj1.getString().compareTo(myObj2.getString());
              if (stringResult == 0) {
                  // Strings are equal, sort by date
                  return myObj1.getDate().compareTo(myObj2.getDate());
              }
              else {
                  return stringResult;
              }
          }
      }
      

      然后排序如下:

      Collections.sort(objectList, new ObjectComparator());
      

      【讨论】:

      • @Krt_Malta 最清楚的?我不这么认为。一方面,它使用了 1.5 之前的非通用版本的比较器,它更加冗长且容易出错。例如,I82Much 的回答要好得多。
      • 我实际上同意我自己应该完成比较器的通用版本,如果您乐于将依赖项引入您的项目,那么 Guava 比较链听起来是值得研究的东西。 (大概它还有很多其他很棒的东西。)
      • @unnamedwill 出于好奇,如果您同意最好使用 Comparator,为什么不编辑您的答案?目前 I82Much 的答案在投票中排名第三,因此一些非常仓促的人可能不会阅读它或这些 cmets,而只是在没有泛型的情况下实现您的答案。
      【解决方案3】:

      使用compare(a,b) 方法实现自定义Comparator,如下所示:

      纯Java:

       public int compare(YourObject o1, YourObject o2) {
          int result = o1.getProperty1().compareTo(o2.getProperty1()));
          if(result==0) result = o1.getProperty2().compareTo(o2.getProperty2());
          return result;
       }
      

      使用Guava(使用ComparisonChain):

      public int compare(YourObject o1, YourObject o2) {
          return ComparisonChain.start()
            .compare(o1.getProperty1(), o2.getProperty1())
            .compare(o1.getProperty2(), o2.getProperty2())
            .result();
       }
      

      使用Commons / Lang(使用CompareToBuilder):

      public int compare(YourObject o1, YourObject o2) {
          return new CompareToBuilder()
            .append(o1.getProperty1(), o2.getProperty1())
            .append(o1.getProperty2(), o2.getProperty2())
            .toComparison();
       }
      

      (所有三个版本都是等效的,但是纯 Java 版本是最冗长的,因此最容易出错。所有三个解决方案都假定 o1.getProperty1()o1.getProperty2() 都实现了 Comparable

      (取自this previous answer of mine


      现在做Collections.sort(yourList, yourComparator)

      【讨论】:

        【解决方案4】:

        比较者的答案是正确的,但不完整。

        StringAndDateComparator implements Comparator<MyObject> {
        
           public int compare(MyObject first, MyObject second) {
                int result = first.getString().compareTo(second.getString());
                if (result != 0) {
                    return result;
                }
                else {
                    return first.getDate().compareTo(second.getDate());
                }
        }
        

        GlazedLists 有一个很好的实用方法,可以将不同的比较器链接在一起,从而避免编写此样板文件。有关详细信息,请参阅chainComparators 方法。

        【讨论】:

          【解决方案5】:

          可以使用 2 个 lambda 表达式对简单数组进行排序:

          Arrays.sort(arr, (i, j) -> (i[0] == j[0] ? j[1] - i[1] : i[0] - j[0]));
          

          表示二维数组 arr 中的两个子数组 i 和 j 将根据数组的第 0 个索引按升序排序。如果第 0 个索引相等,则基于第 1 个索引。

          【讨论】:

            【解决方案6】:

            试试这个方法:

            Collections.sort(list, comparator)

            您当然应该为您的对象有一个自定义的 Comparator 实现,如 Manoj 所述。

            【讨论】:

              【解决方案7】:

              使用java 8和并行排序技术,我们也可以实现如下:

              List<Employee> empss  = getEmployees();
              Comparator<Employee> combinedComparator = Comparator.comparing(Employee::getFName)
                                                                  .thenComparing(Employee::getLName);
              Employee[] emppArr = employees.toArray(new Employee[empss.size()]);
              
              //Parallel sorting
              Arrays.parallelSort(emppArr, combinedComparator);
              

              【讨论】:

                【解决方案8】:
                 package core.java.collection;
                
                import java.util.ArrayList;
                import java.util.Collections;
                import java.util.Comparator;
                import java.util.List;
                
                public class GroupByComparator {
                
                public static void main(String[] args) {
                
                List <StudentTest>  studList = new ArrayList<StudentTest>(); 
                
                    StudentTest s1 = new StudentTest(12 ,"Devendra" ,410);
                    StudentTest s2 = new StudentTest(11 ,"Devendra" ,430);
                    StudentTest s3 = new StudentTest(13 ,"Devendra" ,402);
                    StudentTest s4 = new StudentTest(10 ,"Devendra" ,432);
                    //Assuming that id may be same
                    StudentTest s5 = new StudentTest(14 ,"Singraul" ,432);
                    StudentTest s6 = new StudentTest(14 ,"Abhishek" ,432);
                    StudentTest s7 = new StudentTest(14 ,"Roshan" ,432);
                    StudentTest s8 = new StudentTest(14 ,"Bikas" ,432);
                
                    StudentTest s9 = new StudentTest(15 ,"Devlal" ,450);
                    StudentTest s10 = new StudentTest(15 ,"Devlal" ,359);
                    StudentTest s11= new StudentTest(15 ,"Devlal" ,430);
                    StudentTest s12 = new StudentTest(15 ,"Devlal" ,420);
                
                    studList.add(s1); studList.add(s2); studList.add(s3); studList.add(s4); studList.add(s5);
                    studList.add(s6); studList.add(s7); studList.add(s8); studList.add(s9); studList.add(s10);
                    studList.add(s11); studList.add(s12);
                
                    Collections.sort(studList, new StudentComparator());
                    // group by sorting
                    System.out.println(studList);
                
                }
                
                }
                
                 // Group by Comparator for ascending order
                 class StudentComparator implements Comparator<StudentTest>{
                
                @Override
                public int compare(StudentTest newObj, StudentTest oldObj) {
                    int result =0;
                    // sort by name  first 
                    result=  newObj.getStudName().compareTo(oldObj.getStudName());
                    // sort by student id  second
                    if(result == 0) {
                        result=  newObj.getStudId()-oldObj.getStudId() ; // negative means before
                    }
                     // sort by marks third
                    if(result == 0) {
                        result=   Float.compare(newObj.getMarks(), oldObj.getMarks()); ; // negative means before
                    }
                
                    return result;
                }
                
                  }
                
                class StudentTest{
                
                private int studId ;
                private String studName ;
                private float marks ;
                
                public StudentTest(int studId, String studName, float marks) {
                    super();
                    this.studId = studId;
                    this.studName = studName;
                    this.marks = marks;
                }
                
                public int getStudId() {
                    return studId;
                }
                
                public void setStudId(int studId) {
                    this.studId = studId;
                }
                
                public String getStudName() {
                    return studName;
                }
                
                public void setStudName(String studName) {
                    this.studName = studName;
                }
                
                public float getMarks() {
                    return marks;
                }
                
                public void setMarks(float marks) {
                    this.marks = marks;
                }
                
                @Override
                public String toString() {
                    return "StudentTest [studId=" + studId + ", studName=" + studName + ", marks=" + marks + "]";
                }
                

                }

                【讨论】:

                  【解决方案9】:

                  试试这个方法....

                  studentlist.stream().sorted(Comparator.comparing(Student::getAge).thenComparing(Student::getName)).forEach(System.out::println);
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-03-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多