Java 按多个字段对对象列表进行排序

Java 按多个字段对对象列表进行排序,java,sorting,collections,Java,Sorting,Collections,我有一个Java对象列表,我想根据多个字段进行排序 public class graduationCeremony { String campus; String faculty; String building; } 是否可以使用比较器或可比界面根据多个字段对列表进行排序?我看到的所有示例都只根据一个字段排序。换句话说,可以按“校园”、“教员”或“建筑”进行分类。我想按“校园”排序,然后按“教员”排序,然后按“建筑”排序(正如SQL中存在的那样:按校园、教员、建筑排序

我有一个Java对象列表,我想根据多个字段进行排序

public class graduationCeremony {
    String campus;
    String faculty;
    String building;
}
是否可以使用
比较器
可比
界面根据多个字段对列表进行排序?我看到的所有示例都只根据一个字段排序。换句话说,可以按“校园”、“教员”或“建筑”进行分类。我想按“校园”排序,然后按“教员”排序,然后按“建筑”排序(正如SQL中存在的那样:
按校园、教员、建筑排序

我想这个问题已经解决了,但我不明白大家所接受的答案。有人能详细说明这个答案吗?

希望这有助于:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

class Person implements Comparable {
  String firstName, lastName;

  public Person(String f, String l) {
    this.firstName = f;
    this.lastName = l;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public String toString() {
    return "[ firstname=" + firstName + ",lastname=" + lastName + "]";
  }

  public int compareTo(Object obj) {
    Person emp = (Person) obj;
    int deptComp = firstName.compareTo(emp.getFirstName());

    return ((deptComp == 0) ? lastName.compareTo(emp.getLastName()) : deptComp);
  }

  public boolean equals(Object obj) {
    if (!(obj instanceof Person)) {
      return false;
    }
    Person emp = (Person) obj;
    return firstName.equals(emp.getFirstName()) && lastName.equals(emp.getLastName());
  }
}

class PersonComparator implements Comparator<Person> {
  public int compare(Person emp1, Person emp2) {
    int nameComp = emp1.getLastName().compareTo(emp2.getLastName());
    return ((nameComp == 0) ? emp1.getFirstName().compareTo(emp2.getFirstName()) : nameComp);
  }
}

public class Main {
  public static void main(String args[]) {
    ArrayList<Person> names = new ArrayList<Person>();
    names.add(new Person("E", "T"));
    names.add(new Person("A", "G"));
    names.add(new Person("B", "H"));
    names.add(new Person("C", "J"));

    Iterator iter1 = names.iterator();
    while (iter1.hasNext()) {
      System.out.println(iter1.next());
    }
    Collections.sort(names, new PersonComparator());
    Iterator iter2 = names.iterator();
    while (iter2.hasNext()) {
      System.out.println(iter2.next());
    }
  }
}
import java.util.ArrayList;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.Iterator;
类人实现可比性{
字符串firstName,lastName;
公众人物(字符串f、字符串l){
this.firstName=f;
this.lastName=l;
}
公共字符串getFirstName(){
返回名字;
}
公共字符串getLastName(){
返回姓氏;
}
公共字符串toString(){
返回“[firstname=“+firstname+”,lastname=“+lastname+”]”;
}
公共整数比较(对象对象对象){
人员emp=(人员)obj;
int deptComp=firstName.compareTo(emp.getFirstName());
返回((deptComp==0)?lastName.compareTo(emp.getLastName()):deptComp);
}
公共布尔等于(对象obj){
如果(!(人的obj实例)){
返回false;
}
人员emp=(人员)obj;
返回firstName.equals(emp.getFirstName())和&lastName.equals(emp.getLastName());
}
}
类PersonComparator实现Comparator{
公共整数比较(个人emp1,个人emp2){
int-nameComp=emp1.getLastName().compareTo(emp2.getLastName());
返回((nameComp==0)?emp1.getFirstName().compareTo(emp2.getFirstName()):nameComp);
}
}
公共班机{
公共静态void main(字符串参数[]){
ArrayList name=新的ArrayList();
姓名。添加(新人员(“E”、“T”);
姓名。添加(新人员(“A”、“G”);
姓名。添加(新人员(“B”、“H”);
姓名。添加(新人员(“C”、“J”);
迭代器iter1=names.Iterator();
while(iter1.hasNext()){
System.out.println(iter1.next());
}
Collections.sort(name,newpersoncomparator());
迭代器iter2=names.Iterator();
while(iter2.hasNext()){
System.out.println(iter2.next());
}
}
}

您的比较器如下所示:

public class GraduationCeremonyComparator implements Comparator<GraduationCeremony> {
    public int compare(GraduationCeremony o1, GraduationCeremony o2) {
        int value1 = o1.campus.compareTo(o2.campus);
        if (value1 == 0) {
            int value2 = o1.faculty.compareTo(o2.faculty);
            if (value2 == 0) {
                return o1.building.compareTo(o2.building);
            } else {
                return value2;
            }
        }
        return value1;
    }
}
公共类毕业典礼Comparator实现Comparator{
公共int比较(毕业典礼o1,毕业典礼o2){
int value1=o1.campus.compareTo(o2.campus);
如果(值1==0){
int value2=o1.能力比(o2.能力);
如果(值2==0){
返回o1.建筑物。比较(o2.建筑物);
}否则{
返回值2;
}
}
返回值1;
}
}

基本上,只要到目前为止比较的属性相等(
==0
),它就会继续比较类的每个连续属性。

是的,您完全可以这样做。例如:

public class PersonComparator implements Comparator<Person>
{
    public int compare(Person p1, Person p2)
    {
        // Assume no nulls, and simple ordinal comparisons

        // First by campus - stop if this gives a result.
        int campusResult = p1.getCampus().compareTo(p2.getCampus());
        if (campusResult != 0)
        {
            return campusResult;
        }

        // Next by faculty
        int facultyResult = p1.getFaculty().compareTo(p2.getFaculty());
        if (facultyResult != 0)
        {
            return facultyResult;
        }

        // Finally by building
        return p1.getBuilding().compareTo(p2.getBuilding());
    }
}
公共类PersonComparator实现Comparator
{
公共整数比较(人员p1、人员p2)
{
//假设没有空值和简单的顺序比较
//首先是校园——如果有结果就停止。
int-campusResult=p1.getCampus().compareTo(p2.getCampus());
如果(campusResult!=0)
{
返回campusResult;
}
//下一位是教员
int facultyResult=p1.getFaculty().compareTo(p2.getFaculty());
如果(faultyresult!=0)
{
返回facultyResult;
}
//最后通过构建
返回p1.getBuilding().compareTo(p2.getBuilding());
}
}

基本上你是说,“如果我能通过观察校园(在他们来自不同的校园之前,校园是最重要的领域)来判断哪一个是第一位的,那么我只会返回结果。否则,我会继续比较各系。再次,如果这足以区分他们,请停止。否则,(如果两个人的校园和教员都相同)只需通过构建来比较他们的结果。”

您只需要让您的类继承自


然后以您喜欢的方式实现该方法。

您必须编写自己的compareTo()方法,该方法包含执行比较所需的Java代码

例如,如果我们想比较两个公共领域,校园,然后是教员,我们可以做如下操作:

int compareTo(GraduationCeremony gc)
{
    int c = this.campus.compareTo(gc.campus);

    if( c != 0 )
    {
        //sort by campus if we can
        return c;
    }
    else
    {
        //campus equal, so sort by faculty
        return this.faculty.compareTo(gc.faculty);
    }
}

这很简单,但希望能给你一个想法。有关更多信息,请查阅Comparable和Comparator文档。

如果你事先知道使用哪些字段进行比较,那么其他人会给出正确的答案。
您可能感兴趣的是对集合进行排序,以防在编译时不知道应用哪些标准。 假设您有一个处理城市的程序:



    protected Set<City> cities;
    (...)
    Field temperatureField = City.class.getDeclaredField("temperature");
    Field numberOfInhabitantsField = City.class.getDeclaredField("numberOfInhabitants");
    Field rainfallField = City.class.getDeclaredField("rainfall");
    program.showCitiesSortBy(temperatureField, numberOfInhabitantsField, rainfallField);
    (...)
    public void showCitiesSortBy(Field... fields) {
        List<City> sortedCities = new ArrayList<City>(cities);
        Collections.sort(sortedCities, new City.CityMultiComparator(fields));
        for (City city : sortedCities) {
            System.out.println(city.toString());
        }
    }


您可能需要添加一个额外的精度层,以指定每个字段的排序应该是升序还是后代。我猜解决方案是将
field
对象替换为可以调用
SortedField
的类的对象,该类包含一个
field
对象,以及另一个表示升序或后代的字段

这个问题的第二个答案是一个很好的例子。这有帮助吗:@sim,那么你为什么不花点时间去理解,而不是去寻找代码呢?@Moonbeam,我问题的文本显示我研究了收集和排序,我显示我已经阅读了Stackoverflow上的其他类似问题。你怎么会认为我我只是在寻找代码?下次,请不要无视惠顿定律。@Moonbeam,有时候你会看到代码来理解一个概念。当然像“我的树视图闪烁了一些可怕的东西!”试试这个“谢谢!”对任何人都没有帮助,但这就是为什么这是stac


    public static class CityMultiComparator implements Comparator<City> {
        protected List<Field> fields;

        public CityMultiComparator(Field... orderedFields) {
            fields = new ArrayList<Field>();
            for (Field field : orderedFields) {
                fields.add(field);
            }
        }

        @Override
        public int compare(City cityA, City cityB) {
            Integer score = 0;
            Boolean continueComparison = true;
            Iterator itFields = fields.iterator();

            while (itFields.hasNext() && continueComparison) {
                Field field = itFields.next();
                Integer currentScore = 0;
                if (field.getName().equalsIgnoreCase("temperature")) {
                    currentScore = cityA.getTemperature().compareTo(cityB.getTemperature());
                } else if (field.getName().equalsIgnoreCase("numberOfInhabitants")) {
                    currentScore = cityA.getNumberOfInhabitants().compareTo(cityB.getNumberOfInhabitants());
                } else if (field.getName().equalsIgnoreCase("rainfall")) {
                    currentScore = cityA.getRainfall().compareTo(cityB.getRainfall());
                }
                if (currentScore != 0) {
                    continueComparison = false;
                }
                score = currentScore;
            }

            return score;
        }
    }