在java中对VO的多个动态字段使用Compariable

在java中对VO的多个动态字段使用Compariable,java,comparator,comparable,Java,Comparator,Comparable,我有一节课 public class StudentVO { int age; String name; } 我在两个不同的领域使用同一个类。在一个地方,我需要根据年龄进行分类。在另一个地方,我需要根据名称和位置进行排序 另一个地方,我可能需要根据年龄和姓名进行排序。我该怎么做? 如果有一个字段我可以覆盖compareTo() 有可能做到这一点吗?1)你应该写两个,分别按年龄和姓名排序,然后使用。大概是这样的: class StudentVO { private Strin

我有一节课

public class StudentVO {
   int age;
   String name;  
}
我在两个不同的领域使用同一个类。在一个地方,我需要根据年龄进行分类。在另一个地方,我需要根据名称和位置进行排序 另一个地方,我可能需要根据年龄和姓名进行排序。我该怎么做? 如果有一个字段我可以覆盖
compareTo()

有可能做到这一点吗?

1)你应该写两个,分别按年龄和姓名排序,然后使用。大概是这样的:

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());
  }

}
要根据
名称进行排序

Collections.sort(list,new NameComparator());
Collections.sort(list,new NameComparator());
2) 如果您认为
StudentVO
列表
具有某种自然的排序顺序,那么假设按
年龄进行排序。然后,使用
age
Comparator
表示
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());
    }

 }
要根据
名称进行排序

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

以下是代码片段:

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());
       }
}
公共类StudentNameComparator实现Comparator{
@凌驾
公共整数比较(StudentVO s1、StudentVO s2){
//升序
返回s1.getName().compareTo(s2.getName());
//降序
//返回s2.getName().compareTo(s1.getName());
}
}

根据您的问题,当指定字段的值发生变化时,它也会起作用。您只需记住使用此比较器调用
sort
方法

在java中,比较对象有两种主要方法。 第一个是类本身实现接口,这意味着只有一个实现。 第二个是让类实现接口。这样,您可以为同一个类使用多个比较器

这意味着您可以在StudentVo类上定义3个不同的比较器:一个只比较名称,另一个比较年龄,最后一个比较两个属性

在您的应用程序中,根据您想要比较的内容使用适合您需要的实现。在一个地方,您将比较age Collections.sort(myStudents,new ComparestudentManager())上的学生。在另一个地方,您使用另一个实现


你可以在这篇博文中找到一些解释:

我最近也不得不解决这个问题。不确定这是否与您的场景完全相同,但我必须为网格中的零列或多列编写内存排序,手动保存OOM条件等,因为我的问题范围非常有限

我为每一列编写了一个比较器,一个比较器包含一个比较器列表。当我确定哪些列需要排序以及排序顺序时,我将相应比较器的一个实例添加到比较器列表中。然后,使用链式比较器执行实际排序

public class MyObject
{
    private String name;
    private int age;
    private Date registered;
}
每个比较器都是这样的:

public class NameComparator
    implements Comparator<MyObject>
{
    public int compare(MyObject o1, MyObject o2)
    {
        return o1.getName().compareTo(o2.getName);
    }
}
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<>();
}
公共类名称比较器
执行比较器
{
公共整数比较(MyObject o1,MyObject o2)
{
返回o1.getName().compareTo(o2.getName);
}
}
这适用于链式比较器:

public class NameComparator
    implements Comparator<MyObject>
{
    public int compare(MyObject o1, MyObject o2)
    {
        return o1.getName().compareTo(o2.getName);
    }
}
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<>();
}
公共类ChainedComparator
执行比较器
{
公共整数比较(MyObject o1,MyObject o2){
for(比较器比较器:比较器){
int结果=比较器。比较(o1,o2);
如果(结果!=0){
返回结果;
}
}
返回0;
}
}
私有列表比较器=新的ArrayList();
}

留给你想象的是解析排序和构建链式比较器。实际上,我使这一点变得更复杂了,因为我还合并了一个方向,通过根据需要在链式比较器中对子比较器的调用中交换参数的顺序来实现该方向。

java-8中有一种新的方法 和。您只需提供一个lamda表达式/方法引用,该引用指向
Stream#sorted()
List#sort()
方法

例如,按一个字段排序:

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'}]
List students=Arrays.asList(
新学生VO(20,“鲍勃”),
新学生VO(19,“简”)
);
//按年龄分类
学生们。stream()
.sorted(Comparator.comparing(StudentVO::getAge))
.forEach(System.out::println);
//[StudentVO{age=19,name='Jane'},StudentVO{age=20,name='Bob'}]
//按名称排序
学生们。stream()
.sorted(Comparator.comparing(StudentVO::getName))
.forEach(System.out::println);
//[StudentVO{age=20,name='Bob'},StudentVO{age=19,name='Jane'}]
按几个字段排序:

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'}]
List students=Arrays.asList(
新学生VO(20,“鲍勃”),
新学生VO(19,“Jane”),
新学生VO(21,“鲍勃”)
);
//先按年龄,然后按姓名
学生们。stream()
.排序(比较)
.比较(StudentVO::getAge)
.Then比较(StudentVO::getName)
).forEach(System.out::println);
//[StudentVO{age=19,name='Jane'},StudentVO{age=20,name='Bob'},StudentVO{age=21,name='Bob'}]
//按名字,然后按年龄
学生们。stream()
.排序(比较)
.比较(StudentVO::getName)
.Then比较(StudentVO::getAge)
).forEach(System.out::println);
//[StudentVO{age=20,name='Bob'},StudentVO{age=21,name='Bob'},StudentVO{age=19,name='Jane'}]

安东的方法很好。我用这个:

1-仅按年龄分类:

Collections.sort( studentList, Comparator.comparingInt( student -> student.getAge() ) );
2-名称:

Collections.sort( studentList, Comparator.comparing( student -> student.getName() ) ); 
3-组合:

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

您可以将比较器与比较级联:

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);
List files=new ArrayList();
集合。排序(文件,
新比较器(){
公共int比较(文件file1、文件file2){
返回file2.getName()
.compareTo(file1.getName());
}
}.然后比较(
新比较器(){
公共int比较(文件file1、文件file2){
返回Long.valueOf(file2.getPath().length())
.compareTo(Long.valueOf(file1.getPath().length());
}