Java カスタム エンティティ クラス コレクションの複数ルールの並べ替え

エンティティクラス

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

}

テストデータ

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. カスタム エンティティ クラスは Comparable を継承し、compareTo メソッドを書き換えます (自然な並べ替え)

エンティティクラス

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

テスト

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

結果

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)

注: 大きい順から小さい順に並べ替える場合は、エンティティ クラスの書き換えメソッド CompareTo で this と Student の位置を交換するだけで済みます。また、-Integer.compare( のように先頭に負号を追加することもできます)この年齢、学生の年齢)。


2. Student が参照依存クラスであり、変更できない場合 (Comparator のカスタム オーダー)

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

注: 匿名の内部クラスはラムダ短縮表現を使用できます


  1. データの一部をフィルターしてコレクションを並べ替えるには、stream+Comparator を使用して並べ替えをカスタマイズする必要があります。

ストリームの一般的なメソッド ( https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html )

修飾子と型

方法と説明

長さ

カウント()

このストリーム内の要素の数を返します。

ストリーム<T>

明確()

このストリームの個別の要素で構成されるストリームを返します (Object.equals(Object) に従って)。

ストリーム<T>

filter(述語<?スーパーT>述語)

指定された述語に一致するこのストリームの要素で構成されるストリームを返します。

空所

forEach(Consumer<? super T> アクション)

このストリームの各要素に対して操作を実行します。

ストリーム<T>

制限(長い最大サイズ)

このストリームの要素で構成されるストリームを、長さが maxSize を超えないように切り詰められて返します。

<R> ストリーム<R>

map(Function<? super T,? extends R> マッパー)

指定された関数をこのストリームの要素に適用した結果で構成されるストリームを返します。

オプション<T>

max(コンパレータ<?スーパーT>コンパレータ)

このストリームの最大の要素を返します。

オプション<T>

min(コンパレータ<?スーパーT>コンパレータ)

このストリームの最小の要素を返します。

ストリーム<T>

スキップ(長いn)

ストリームの最初の n 要素を破棄した後、ストリームの残りの要素で構成されるストリームを返します。

ストリーム<T>

ソート済み()

このストリームの要素で構成されるストリームを自然な順序でソートして返します。

ストリーム<T>

ソート済み(コンパレータ<?スーパーT>コンパレータ)

指定された 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);

結果

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. コンパレータとコンパレータの違い

エンティティ クラス構造を変更せずに Comparator を使用することをお勧めします。これにより、結合の度合いが軽減されます。

Comparable には 1 つの並べ替えルールのみを指定できますが、Comparator には複数のクラスと複数の並べ替えルールを記述できるため、より柔軟です。

おすすめ

転載: blog.csdn.net/m0_68705273/article/details/129720449