Java8のComparatorの使い方(Collectionsクラスのsortメソッド)

javaJava8

Java8のComparatorの使い方(Collectionsクラスのsortメソッド)

Java8からComparatorの使い方が大変簡単になりました。

Integer型のlistが適当に並んでいるとします。

これを昇順にソートするには以下のようにnaturalOrderメソッドを使います。

Collections.sort(list, Comparator.naturalOrder());

以下、例です。

import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;

public class Sample {
  public static void main(String[] args) {
    List list = Arrays.asList(3,2,8,4,1);// 順不同
    Collections.sort(list, Comparator.naturalOrder());
    System.out.println(list);
  }
}

結果は以下のように昇順にソートされます。

1, 2, 3, 4, 8

逆に降順にソートしたい場合はreverseOrderメソッドを使います。

import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;

public class Sample {
  public static void main(String[] args) {
    List list = Arrays.asList(3,2,8,4,1);// 順不同
    Collections.sort(list, Comparator.reverseOrder());
    System.out.println(list);
  }
}

結果は以下のように降順にソートされます。

8, 4, 3, 2, 1

reverseメソッド

Collections.reverseメソッドはリストを単純に逆順(addした順の逆)に並び替えます。

import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;

public class Sample {
  public static void main(String[] args) {
    List list = Arrays.asList(3,2,8,4,1);// 順不同
    Collections.reverse(list);
    System.out.println(list);
  }
}

結果は以下のようにaddした順の逆順に並び替えられます。

1, 4, 8, 2, 3

Streamのsortedを使う

Streamのsortedを使ってソートすることも可能です。

import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;

public class Sample {
  public static void main(String[] args) {
    List<Integer> list = Arrays.asList(3,2,8,4,1);// 順不同
    Object[] ret = list.stream().sorted(Comparator.naturalOrder()).toArray();
    System.out.println(Arrays.toString(ret));
  }
}

Comparator.naturalOrder()を指定しているので、結果は以下のように昇順にソートされます。降順にソートしたい場合はComparator.reverseOrder()を指定します。

1, 2, 3, 4, 8

Listの要素が独自クラスのインスタンス(オブジェクト)の場合

ListがintだったりStringだったりする場合は理解できるけど、独自クラスだった場合のソート方法がわからなかったりします。

従業員を表すEmployeeクラスです。

public class Employee {

  // フィールド
  private String name;
  private int age;

  // コンストラクタ
  public Employee(String name, int age) {
    this.name = name;
    this.age = age;
  }

  // 各アクセサ
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
}

Employeeクラスのオブジェクトのリストのソートをします。以下はList.sortメソッド(since 1.8)を使用して名前の昇順でソートする例です。

List<Employee> list = new ArrayList<Employee>();
        
list.add(new Employee("tanaka", 44));
list.add(new Employee("takahashi", 40));
list.add(new Employee("minami", 30));
list.add(new Employee("higashiguchi", 32));
list.add(new Employee("adachi", 200));
list.add(new Employee("rasubusu", 25));
// 名前の昇順にソート
list.sort(Comparator.comparing(Employee::getName,Comparator.naturalOrder()));
// 標準出力
list.forEach(s -> System.out.println(s.getName() + " : " + s.getAge()));

その他にもソート方法があります。例えばComparatorのcompareメソッドをオーバーライドするなどです。

List<Employee> sortedList = list.stream().sorted(new Comparator<Employee>(){
  @Override
  public int compare(Employee o1, Employee o2) {
    return o1.getName().compareTo(o2.getName());
  }
}).collect(Collectors.toList());
// 標準出力
sortedList.forEach(s -> System.out.println(s.getName() + " : " + s.getAge()));

Comparator.comparingメソッド

これもComparator.comparingメソッドを使用すればもうちょっときれいに書けます。

Comparator<Employee> comp = Comparator.comparing(Employee::getName);
List<Employee> sortedList = list.stream().sorted(comp).collect(Collectors.toList());
// 標準出力
sortedList.forEach(s -> System.out.println(s.getName() + " : " + s.getAge()));

Collections.sortメソッドの第一引数にリスト、第二引数にComparator.comparingメソッドを指定することでソートすることができます。

Comparator<Employee> comp = Comparator.comparing(Employee::getName,Comparator.nullsFirst(Comparator.naturalOrder()));
Collections.sort(list, comp);
// 標準出力
list.forEach(s -> System.out.println(s.getName() + " : " + s.getAge()));

ソートするキーにnullが含まれる場合

今までの書き方でも問題ないと思いますが、ソートキーにnullが含まれる可能性がある場合はヌルポで落ちる可能性があります。

この場合は、nullを考慮してあげます。

nullメソッド
先頭行Comparator.nullsFirstメソッド
最終行Comparator.nullsLastメソッド

以下はnullの場合、先頭にもってきて名前順にソートする例です。

List<Employee> list = new ArrayList<Employee>();

list.add(new Employee("tanaka", 44));
list.add(new Employee("takahashi", 40));
list.add(new Employee("minami", 30));
list.add(new Employee("higashiguchi", 32));
list.add(new Employee("adachi", 200));
list.add(new Employee("rasubusu", 25));
list.add(new Employee(null, 25)); // キーがnullになっている

Comparator<Employee> comp = Comparator.comparing(Employee::getName,Comparator.nullsFirst(Comparator.naturalOrder()));
List<Employee> sortedList = list.stream().sorted(comp).collect(Collectors.toList());

sortedList.forEach(s -> System.out.println(s.getName() + " : " + s.getAge()));

Java8のComparatorインタフェースで複合ソートする

コメント

タイトルとURLをコピーしました