Using Comparable for multiple dynamic fields of VO in java

后端 未结 7 1721
伪装坚强ぢ
伪装坚强ぢ 2020-11-28 11:36

I have a class

public class StudentVO {
   int age;
   String name;  
}

I used the same class in two different areas. At one place i need t

相关标签:
7条回答
  • 2020-11-28 12:03

    Anton's approach is quite good. I use this one:

    1- For sorting only by age:

    Collections.sort( studentList, Comparator.comparingInt( student -> student.getAge() ) );
    

    2- For name:

    Collections.sort( studentList, Comparator.comparing( student -> student.getName() ) ); 
    

    3- Combination:

    Collections.sort( studentList, Comparator.comparing( student -> student.getName() ).thenComparingInt( student -> student.getAge() ) ); 
    
    0 讨论(0)
  • 2020-11-28 12:05

    You can cascade the comparators with thenComparing:

    List<File> files = new ArrayList();
    Collections.sort(files,
    
            new Comparator<File>() {
                public int compare(File file1, File file2) {
                    return file2.getName()
                            .compareTo(file1.getName());
                }
            }.thenComparing(
                    new Comparator<File>() {
                        public int compare(File file1, File file2) {
                            return Long.valueOf(file2.getPath().length())
                                    .compareTo(Long.valueOf(file1.getPath().length()));
                        }
                    }
            )
    
    );
    // Collections.reverse(list);
    

    https://www.eovao.com/en/a/sort%20elements%20java/4/how-to-sort-objects-in-java---multiple-comparison-sort-list

    0 讨论(0)
  • 2020-11-28 12:06

    1)You should write two Comparator for sorting on age and name separately, and then use the Collections.sort(List,Comparator). Something like this:

    class StudentVO {
      private String name;
      private int 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;
      }
    }
    
    class AgeComparator implements Comparator<StudentVO> {
    
    @Override
    public int compare(StudentVO o1, StudentVO o2) {
        Integer age1 = o1.getAge();
        Integer age2 = o2.getAge();
        return age1.compareTo(age2);
      }
    
    }
    
    class NameComparator implements Comparator<StudentVO> {
    
      @Override
      public int compare(StudentVO o1, StudentVO o2) {
          return o1.getName().compareTo(o2.getName());
      }
    
    }
    

    And then use them, To sort based on age:

    Collections.sort(list,new AgeComparator());
    

    to sort based on name:

    Collections.sort(list,new NameComparator());
    

    2) If you think that the List of StudentVO has some natural order of sorting, say suppose sort by age. Then, use Comparable for age and Comparator for name.

     class StudentVO implements Comparable<StudentVO>{
        private String name;
        private int 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;
        }
        @Override
        public int compareTo(StudentVO o) {
            return ((Integer)getAge()).compareTo(o.getAge());
        }
    }
    
    class NameComparator implements Comparator<StudentVO> {
    
        @Override
        public int compare(StudentVO o1, StudentVO o2) {
            return o1.getName().compareTo(o2.getName());
        }
    
     }
    

    And then use them, To sort based on age:

    Collections.sort(list);
    

    to sort based on name:

    Collections.sort(list,new NameComparator());
    
    0 讨论(0)
  • 2020-11-28 12:09

    There is new approach for this in java-8 see Comparator#comparing and Comparator#thenComparing. All you need is to provide a lamda expression/method reference either to Stream#sorted() or List#sort() method.

    For example sorting by one field:

    List<StudentVO> students = Arrays.asList(
            new StudentVO(20,"Bob"),
            new StudentVO(19, "Jane")
    );
    // sort by age
    students.stream()
            .sorted(Comparator.comparing(StudentVO::getAge))
            .forEach(System.out::println);
    // [StudentVO{age=19, name='Jane'},StudentVO{age=20, name='Bob'}]
    // sort by name
    students.stream()
            .sorted(Comparator.comparing(StudentVO::getName))
            .forEach(System.out::println);
    // [StudentVO{age=20, name='Bob'}, StudentVO{age=19, name='Jane'}]
    

    Sorting by a few fields:

    List<StudentVO> students = Arrays.asList(
            new StudentVO(20,"Bob"),
            new StudentVO(19, "Jane"),
            new StudentVO(21,"Bob")
    );
    // by age and then by name
    students.stream()
            .sorted(Comparator
                    .comparing(StudentVO::getAge)
                    .thenComparing(StudentVO::getName)
            ).forEach(System.out::println);
    // [StudentVO{age=19, name='Jane'}, StudentVO{age=20, name='Bob'}, StudentVO{age=21, name='Bob'}]
    // by name an then by age
    students.stream()
            .sorted(Comparator
                    .comparing(StudentVO::getName)
                    .thenComparing(StudentVO::getAge)
            ).forEach(System.out::println);
    // [StudentVO{age=20, name='Bob'}, StudentVO{age=21, name='Bob'}, StudentVO{age=19, name='Jane'}]
    
    0 讨论(0)
  • 2020-11-28 12:11

    I recently had to solve this problem, too. Not sure if this is exactly the same scenario as yours, but I had to write an in-memory sort for zero or more columns of a grid, handwaving over OOM conditions, etc, because my problem was very limited in scope.

    I wrote a comparator for each column and a comparator that took a list of comparators. As I identified which columns needed to be sorted and in what order, I added an instance of the corresponding comparator to the list of comparators. Then, use the chained comparator to execute the actual sort.

    public class MyObject
    {
        private String name;
        private int age;
        private Date registered;
    }
    

    So, something like this for each comparator:

    public class NameComparator
        implements Comparator<MyObject>
    {
        public int compare(MyObject o1, MyObject o2)
        {
            return o1.getName().compareTo(o2.getName);
        }
    }
    

    This for the chained comparator:

    public class ChainedComparator
        implements Comparator<MyObject>
    {
        public int compare(MyObject o1, MyObject o2) {
            for(Comparator<MyObject> comparator : comparators) {
                int result = comparator.compare(o1,o2);
                if(result != 0) {
                    return result;
                }
            }
            return 0;
        }
    }
        private List<Comparator<MyObject>> comparators = new ArrayList<>();
    }
    

    Left to your imagination is parsing the sorts and building the chained comparator. I actually made this a bit more complicated because I also incorporated a direction which I implemented by swapping the order of parameters in the call to the sub-comparator in the chained comparator as needed.

    0 讨论(0)
  • 2020-11-28 12:12

    Here is the code snippet:

    public class StudentNameComparator implements Comparator<StudentVO>{
    
    @Override
    public int compare(StudentVO s1, StudentVO s2) {
    
            //ascending order
            return s1.getName().compareTo(s2.getName());
    
            //descending order
            //return s2.getName().compareTo(s1.getName());
           }
    }
    

    According to your question, it will also work when values of specified field will change. You have only to remember to call sort method with this comparator.

    0 讨论(0)
提交回复
热议问题