Java custom entity class collection multi-rule sorting

Entity class

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student{
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 国籍
     */
    private String nationality;

}

Test Data

List<Student> students = new ArrayList<>();
Student student1 = new Student("java", 22, "Chinese");
Student student2 = new Student("go", 11, "USA");
Student student3 = new Student("js", 20, "Japan");
Student student4 = new Student("python", 16, "Thailand");
Student student5 = new Student("php", 33, "Chinese");
Student student6 = new Student("php", 16, "Chinese");
Student student7 = new Student("java", 16, "Thailand");
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
students.add(student5);
students.add(student6);
students.add(student7);

1. The custom entity class inherits Comparable and rewrites the compareTo method (natural sorting)

Entity class

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Comparable<Student>{
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 国籍
     */
    private String nationality;


    /**
     *
     * @param student
     * @return
     * 如果返回值为负数:当前对象大
     * 如果返回值为正数:当前对象小
     * 如果返回值为0:一样大
     */
    @Override
    public int compareTo(Student student) {
        // lombok已经重写equals方法,字段都相等时对象才相等
        if (this.equals(student)) {
            return 0;
        }
        int ageCompare = Integer.compare(this.age, student.age);
        if (ageCompare != 0) {
            return ageCompare;
        }
        int nationalityCompare = this.nationality.compareTo(student.nationality);
        if (nationalityCompare != 0) {
            return nationalityCompare;
        }
        return this.name.compareTo(student.name);
    }
}

test

// 先根据年龄从小到大,再根据国籍从小到大,最后根据姓名从小到大
Collections.sort(students);
students.forEach(System.out::println);

result

Student(name=go, age=11, nationality=USA)
Student(name=php, age=16, nationality=Chinese)
Student(name=java, age=16, nationality=Thailand)
Student(name=python, age=16, nationality=Thailand)
Student(name=js, age=20, nationality=Japan)
Student(name=java, age=22, nationality=Chinese)
Student(name=php, age=33, nationality=Chinese)

Note: If you want to sort from large to small, just exchange this and student in the overridden method compareTo of the entity class; you can also add a negative sign in front, such as -Integer.compare(this.age, student .age).


2. If Student is a reference-dependent class and cannot be modified (Comparator custom ordering)

students.sort(new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        if (o1.equals(o2)) {
            return 0;
        }
        int ageCompare = Integer.compare(o1.getAge(), o2.getAge());
        if (ageCompare != 0) {
            return ageCompare;
        }
        int nationalityCompare = o1.getNationality().compareTo(o2.getNationality());
        if (nationalityCompare != 0) {
            return nationalityCompare;
        }
        return o1.getName().compareTo(o2.getName());
    }
});

Note: Anonymous inner classes can use lambda shorthand


  1. To filter part of the data and then sort the collection, you need to use stream+Comparator to customize the sorting

Common methods of stream ( https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html )

modifiers and types

Method and Description

long

count()

Returns the count of elements in this stream.

Stream<T>

distinct()

Returns a stream consisting of the distinct elements of this stream (according to Object.equals(Object)).

Stream<T>

filter(Predicate<? super T> predicate)

Returns a stream consisting of elements of this stream that match the given predicate.

void

forEach(Consumer<? super T> action)

Performs an operation on each element of this stream.

Stream<T>

limit(long maxSize)

Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.

<R> Stream<R>

map(Function<? super T,? extends R> mapper)

Returns a stream consisting of the results of applying the given function to the elements of this stream.

Optional<T>

max(Comparator<? super T> comparator)

Returns the largest element of this stream.

Optional<T>

min(Comparator<? super T> comparator)

Returns the smallest element of this stream.

Stream<T>

skip(long n)

After discarding the first n elements of the stream, returns a stream consisting of the remaining elements of the stream.

Stream<T>

sorted()

Returns a stream consisting of the elements of this stream, sorted in natural order.

Stream<T>

sorted(Comparator<? super T> comparator)

Returns a stream consisting of the elements of this stream sorted according to the provided Comparator.

students.stream()
        // 学生年龄大于16岁
        .filter(student -> student.getAge() >= 16)
        .sorted((Student o1, Student o2) -> {
            if (o1.equals(o2)) {
                return 0;
            }
            int ageCompare = Integer.compare(o1.getAge(), o2.getAge());
            if (ageCompare != 0) {
                return ageCompare;
            }
            int nationalityCompare = o1.getNationality().compareTo(o2.getNationality());
            if (nationalityCompare != 0) {
                return nationalityCompare;
            }
            return o1.getName().compareTo(o2.getName());
        })
        .forEach(System.out::println);

result

Student(name=php, age=16, nationality=Chinese)
Student(name=java, age=16, nationality=Thailand)
Student(name=python, age=16, nationality=Thailand)
Student(name=js, age=20, nationality=Japan)
Student(name=java, age=22, nationality=Chinese)
Student(name=php, age=33, nationality=Chinese)

4. The difference between Comparator and Comparable

It is recommended to use Comparator, without modifying the entity class structure, which can reduce the degree of coupling

Comparable can only be given one sorting rule, and Comparator can write multiple classes and multiple sorting rules, which is more flexible

Guess you like

Origin blog.csdn.net/m0_68705273/article/details/129720449