简体   繁体   English

使用 2 个条件在 Java 中对列表进行排序

[英]Sorting a list in Java using 2 criteria

I have a list of objects.我有一个对象列表。 Each object contains a String and a Date (amongst others).每个对象都包含一个String和一个Date (等等)。

I want to first sort by the String and then by the Date .我想先按String排序,然后按Date排序。

How could this be done in the cleanest way possible?这怎么可能以最干净的方式完成?

Thanks!谢谢!

Krt_Malta Krt_马耳他

With Java 8, this is really easy.使用 Java 8,这真的很容易。 Given给定的

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

You can easily sort a list as follows:您可以轻松地按如下方式对列表进行排序:

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

Given an object class that looks like this:给定一个如下所示的对象类:

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

Write a custom comparator class like so:编写一个自定义比较器类,如下所示:

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

Then sort as follows:然后排序如下:

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

Implement a custom Comparator , using a compare(a,b) method like the following:使用compare(a,b)方法实现自定义Comparator ,如下所示:

Plain 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;
 }

With Guava (using ComparisonChain ):使用番石榴(使用ComparisonChain):

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

With Commons / Lang (using CompareToBuilder ):使用Commons / Lang (使用CompareToBuilder ):

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

(All three versions are equivalent, but the plain Java version is the most verbose and hence most error-prone one. All three solutions assume that both o1.getProperty1() and o1.getProperty2() implement Comparable ). (所有三个版本都是等效的,但纯 Java 版本是最冗长的,因此最容易出错。所有三个解决方案都假设o1.getProperty1()o1.getProperty2()实现了Comparable )。

(Taken from this previous answer of mine ) (取自我之前的回答


now do Collections.sort(yourList, yourComparator)现在做Collections.sort(yourList, yourComparator)

The Comparators answer is correct but incomplete.比较器的答案是正确但不完整的。

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 has a nice utility method to chain together different comparators to save you from writing this boilerplate. GlazedLists 有一个很好的实用方法,可以将不同的比较器链接在一起,从而避免编写此样板文件。 See the chainComparators method for more information.有关更多信息,请参阅chainComparators方法。

A simple array can be sorted using 2 lambda experessions as:一个简单的数组可以使用 2 个 lambda 表达式进行排序:

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

means two subarrays i & j within a 2D array arr will be sorted in ascending order based on 0th index of arrays.意味着二维数组arr 中的两个子数组 i 和 j 将根据数组的第 0 个索引按升序排序。 And if 0th index is equal, then based on 1st index.如果第 0 个索引相等,则基于第一个索引。

Using java 8 and parallel sorting technique, we can also achieve this as follows:使用 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);

Try this method:试试这个方法:

Collections.sort(list, comparator)

You should of course have a custom Comparator implementation for your object, as stated by Manoj.正如 Manoj 所述,您当然应该为您的对象自定义 Comparator 实现。

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

} }

试试这个方法....

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM