エンティティクラス
@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());
}
});
注: 匿名の内部クラスはラムダ短縮表現を使用できます
データの一部をフィルターしてコレクションを並べ替えるには、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 には複数のクラスと複数の並べ替えルールを記述できるため、より柔軟です。