Javaでリストを複数の条件でソートしたい時は、Comparator クラスの comparing() と thenComparing() を使うと簡単に実現できる。
例えば、以下の Work クラスのオブジェクトが複数入った List があるとする。
class Work { private int timeToFinish; // 仕事が終わるまでにかかる時間 private int reward; // 報酬 Work(int timeToFinish, int reward) { this.timeToFinish = timeToFinish; this.reward = reward; } public int getTimeToFinish() { return timeToFinish; } public int getReward() { return reward; } }
その List について、報酬が高い順に、そして報酬が同じだったら、仕事が終わるまでにかかる時間が少ない順でソートしたいとする。
# つまり、ソートの第一条件が報酬(降順)で、第二条件が仕事が終わるまでにかかる時間(昇順)。
このソートを実現するには以下のように実装する。
List<Work> works = new ArrayList<>();
・・・
Comparator<Work> workComparator =
Comparator.comparing(Work::getReward, Comparator.reverseOrder())
.thenComparing(Work::getTimeToFinish);
works.sort(workComparator);
ソートの第一条件にソートの第二条件を繋げて Comparator を作成し、それを sortメソッドの引数として与えている。
以上を踏まえて、例えば以下を実行すると、
List<Work> works = new ArrayList<>(); works.add(new Work(1, 3)); works.add(new Work(3, 8)); works.add(new Work(2, 6)); works.add(new Work(3, 7)); works.add(new Work(1, 4)); works.add(new Work(4, 6)); Comparator<Work> workComparator = Comparator.comparing(Work::getReward, Comparator.reverseOrder()) .thenComparing(Work::getTimeToFinish); works.sort(workComparator); for (Work work : works) { System.out.println("TimeToFinish: " + work.getTimeToFinish() + ", Reward: " + work.getReward()); } }
出力結果は以下にようになる。
TimeToFinish: 3, Reward: 8
TimeToFinish: 3, Reward: 7
TimeToFinish: 2, Reward: 6
TimeToFinish: 4, Reward: 6
TimeToFinish: 1, Reward: 4
TimeToFinish: 1, Reward: 3
期待通り、報酬が高い順に、報酬が同じだったらかかる時間が短い順にソートされている。