yohhoyの日記

技術的メモをしていきたい日記

Comparator with ラムダ式

Java8で機能拡張されたjava.util.Comparator*1インタフェースについてメモ。コンパレータオブジェクトを生成・合成するstatic/defaultメソッドが追加された。

メソッド 機能
naturalOrder() (自然順序付け)コンパレータを生成
reverseOrder() (自然順序付け)逆順コンパレータを生成
comparing(e) ソートキー(U型)抽出関数eを指定したコンパレータを生成
comparing(e,u) ソートキー(U型)抽出関数eと(U型)コンパレータuを指定したコンパレータを生成
comparingInt(e) ソートキー(int型)抽出関数eを指定したコンパレータを生成
comparingLong(e) ソートキー(long型)抽出関数eを指定したコンパレータを生成
comparingDouble(e) ソートキー(double型)抽出関数eを指定したコンパレータを生成
c.thenComparing(t) (T型)コンパレータtを追加接続した辞書式順序付けコンパレータを返す
c.thenComparing(e) ソートキー(U型)抽出eを指定した辞書式順序付けコンパレータを返す
c.thenComparing(e,u) ソートキー(U型)抽出関数eと(U型)コンパレータuを指定した辞書式順序付けコンパレータを返す
c.thenComparingInt(e) ソートキー(int型)抽出関数eを指定した辞書式順序付けコンパレータを返す
c.thenComparingLong(e) ソートキー(long型)抽出関数eを指定した辞書式順序付けコンパレータを返す
c.thenComparingDouble(e) ソートキー(double型)抽出関数eを指定した辞書式順序付けコンパレータを返す
nullsFirst(c) nullを最小値とみなすコンパレータを返す
nullsLast(c) nullを最大値とみなすコンパレータを返す
c.reversed() 順序反転させたコンパレータを返す

ノート:自然順序(natural order)=java.lang.Comparableインタフェースを実装したクラス、辞書式順序(lexicographic order)=wikipedia:ja:辞書式順序

例1:逆順ソート

// Java8
String[] a = /*...*/;
Arrays.sort(a, Comparator.reverseOrder());
// Java7以前
Arrays.sort(a,
  new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
      return o2.compareTo(o1);
    }
  });

例2:辞書式順序付け

// Java8
class Person {
  //...
  public String getName();
  public String getGender();
  public int getAge();
};
Person[] people = /*...*/;

// Age->Name->Gender の辞書式順序でソート
Arrays.sort(people,
  Comparator.comparingInt(Person::getAge)
            .thenComparing(Person::getName)
            .thenComparing(Person::getGender));
// Java7以前
Arrays.sort(people,
  new Comparator<Person>() {
    @Override
    public int compare(Person o1, Person o2) {
      int ret;
      // NOTE: Integer#compare(int,int)はJava7以降
      ret = Integer.compare(o1.getAge(), o2.getAge());
      if (ret != 0)
        return ret;
      ret = o1.getName().compareTo(o2.getName());
      if (ret != 0)
        return ret;
      return o1.getGender().compareTo(o2.getGender());
    }
  });

例3:null許容

// Java8
class Item {
  //...
  public String getCode();     // 非null保証
  public String getSubCode();  // null許容
};
Item[] items = /*...*/;

// Code->SubCode(nullは最大値) の辞書式順序でソート
Arrays.sort(items,
  Comparator.comparing(Item::getCode)
            .thenComparing(Item::getSubCode,
               Comparator.nullsLast(Comparator.naturalOrder())));
// Java7以前
Arrays.sort(items,
  new Comparator<Item>() {
    @Override
    public int compare(Item o1, Item o2) {
      int ret;
      ret = o1.getCode().compareTo(o2.getCode());
      if (ret != 0)
        return ret;
      String subCode1 = o1.getSubCode();
      String subCode2 = o2.getSubCode();
      if (subCode1 == null) {
        if (subCode2 == null)
          ret = 0;  // null == null
        else
          ret = 1;  // null > o2
      } else {
        if (subCode2 == null)
          ret = -1;  // o1 < null
        else
          ret = subCode1.compareTo(subCode2);
      }
      return ret;
    }
  });

関連URL