使用 2 个标准对 Java 中的列表进行排序

问题描述 投票:0回答:9

我有一个对象列表。每个对象都包含一个

String
和一个
Date
(等等)。

我想先按

String
排序,然后再按
Date
排序。

如何以最干净的方式完成此操作?

谢谢!

Krt_马耳他

java sorting
9个回答
34
投票

从 Java 8 开始,这真的很容易。在

…comparing…
 上使用 
Comparator
方法。

鉴于:

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

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

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

23
投票

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

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

8
投票

使用

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

普通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;
 }

番石榴(使用

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
)。

(摘自我之前的回答


现在做

Collections.sort(yourList, yourComparator)


7
投票

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

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 个索引。


2
投票
 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 + "]";
}

}


1
投票

试试这个方法:

Collections.sort(list, comparator)

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


1
投票

使用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);

0
投票

试试这个方法......

studentlist.stream().sorted(Comparator.comparing(Student::getAge).thenComparing(Student::getName)).forEach(System.out::println);
© www.soinside.com 2019 - 2024. All rights reserved.