はしくれエンジニアもどきのメモ

情報系技術・哲学・デザインなどの勉強メモ・備忘録です。

Java のソートはComparator で昇順、降順を指定

Java のソートはComparator で昇順、降順を指定

Java8 からソートは、 Comparatorインターフェースで 昇順、降順を手軽に指定できるようなのでメモ。

環境

Arrays.sortの場合

配列のソートには、Arrays.sort() が使える。

Arrays.sortの場合(プリミティブ型の配列)

import java.util.Arrays; する必要がある。 昇順に並べ替えることができる。int などのプリミティブ型は昇順にしか並べ替えることができない。

クイックソートが使われている模様。


import java.util.Arrays;

int array[] = {3, 2, 1, 5, 4};
Arrays.sort(array);
System.out.println(Arrays.toString(array));

result:
[1, 2, 3, 4, 5]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html#sort-int:A-

Arrays.sortの場合(Comparatableを実装した配列)

Integer などComparatable を実装した配列では、 関数型インターフェースComparator(比較関数)を使用して昇順、降順を指定できる。

参考:Comparator (Java Platform SE 8)

昇順は、Comparator.naturalOrder() を、 降順は、Comparator.reverseOrder() を指定すればいい。

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html#naturalOrder--


import java.util.Arrays;
import java.util.Comparator;

Integer array[] = {3, 2, 1, 5, 4};
Arrays.sort(array, Comparator.naturalOrder()); // 昇順になる
System.out.println(Arrays.toString(array));

result:
[1, 2, 3, 4, 5]

Arrays.sort(array, Comparator.reverseOrder()); // 降順になる
System.out.println(Arrays.toString(array));

result:
[5, 4, 3, 2, 1]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html#sort-T:A-java.util.Comparator-

Collections.sort の場合

Collections.sort() の場合でも同様。 Collection型はプリミティブ型が使えないので、 Comparatable が実装されている型であれば、 Comparator で昇順と降順ができる。


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

List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 3, 2, 1, 4, 5);

Collections.sort(list); // 未指定ならば昇順
System.out.println(list.toString());

result:
[1, 2, 3, 4, 5]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/Collections.html#sort-java.util.List-

Collection型オブジェクト自体でもsort 関数が呼べる。


list.sort(Comparator.naturalOrder()); // 昇順
System.out.println(list.toString());

result:
[1, 2, 3, 4, 5]

Arrays.sort() 同様、第2引数でComparatable を指定する。


Collections.sort(list, Comparator.reverseOrder());
System.out.println(list.toString());

result:
[5, 4, 3, 2, 1]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/Collections.html#sort-java.util.List-java.util.Comparator-

stream.sorted の場合

StreamAPIでもソートは可能、 stream.sorted()メソッドを使う。

Streamを多用する場合はこれ知ってるだけで良さげ。 基本ワンライナーで書ける。

stream.sorted の場合(プリミティブ型)

今まで同様、Comparatableを実装していないプリミティブ型の Streamでは、ソートは昇順しかできない。


int array[] = {3, 2, 1, 5, 4};

System.out.println(
  Arrays.toString(Arrays.stream(array).sorted().toArray()) // 昇順
);

result:
[1, 2, 3, 4, 5]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html#sorted--

stream.sorted の場合(Comparatableを実装した型)

Comparatable を実装した型であれば、 .sorted(Comparator.naturalOrder) で昇順、降順を指定できる。


Integer array[] = {3, 2, 1, 5, 4};

System.out.println(
  Arrays.toString(Arrays.stream(array).sorted(Comparator.naturalOrder()).toArray()) // 昇順
);

result:
[1, 2, 3, 4, 5]

System.out.println(
  Arrays.toString(Arrays.stream(array).sorted(Comparator.reverseOrder()).toArray()) // 降順
);

result:
[5, 4, 3, 2, 1]

参考:http://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html#sorted-java.util.Comparator-

Comparatable を実装していない独自型の場合

Comparatable を実装していない独自型でも、 Comparatable.comparing() で指定の値でソートすることできる。

Comparatable を実装していない独自型の場合(配列)

名前String name_ と年齢int age_ のメンバを持った独自クラスPerson を考えた場合、String name_ でのソートや、 int age_ でのソートができる。

Comparator.comparing(Person::getAge) とすれば、 年齢のソートとなる。


class Person {
    private String name_;
    private int age_;

    public Person(String name, int age) {
        this.name_ = name;
        this.age_ = age;
    }

    public String getName() {
        return this.name_;
    }

    public int getAge() {
        return this.age_;
    }

    @Override
    public String toString() {
        return this.name_ + ", " + this.age_;
    }
}

Person people[] = {
   new Person("Sato", 20),
   new Person("Tanaka", 15),
   new Person("Suzuki", 35),
   new Person("Yamamoto", 40),
   new Person("Koyama", 10)
 };

Arrays.sort(people, Comparator.comparing(Person::getAge));
System.out.println(Arrays.toString(people));

result:
[Koyama, 10, Tanaka, 15, Sato, 20, Suzuki, 35, Yamamoto, 40]

降順にしたい場合は、 Comparator.comparing(Person::getAge).reversed() とすればいい。


Arrays.sort(people, Comparator.comparing(Person::getAge).reversed());
System.out.println(Arrays.toString(people));

result:
[Yamamoto, 40, Suzuki, 35, Sato, 20, Tanaka, 15, Koyama, 10]

Comparatable を実装していない独自型の場合(stream)

Stream でも同様にソートできる。

年齢のソート(昇順):


System.out.println(
  Arrays.toString(Arrays.stream(people).sorted(Comparator.comparing(Person::getAge)).toArray())
);

result:
[Koyama, 10, Tanaka, 15, Sato, 20, Suzuki, 35, Yamamoto, 40]

年齢のソート(降順):


System.out.println(
  Arrays.toString(Arrays.stream(people).sorted(Comparator.comparing(Person::getAge).reversed()).toArray())
);

result:
[Yamamoto, 40, Suzuki, 35, Sato, 20, Tanaka, 15, Koyama, 10]

名前順(昇順):


System.out.println(
  Arrays.toString(Arrays.stream(people).sorted(Comparator.comparing(Person::getName)).toArray())
);

result:
[Koyama, 10, Sato, 20, Suzuki, 35, Tanaka, 15, Yamamoto, 40]

名前順(降順):


System.out.println(
  Arrays.toString(Arrays.stream(people).sorted(Comparator.comparing(Person::getName).reversed()).toArray())
);

result:
[Yamamoto, 40, Tanaka, 15, Suzuki, 35, Sato, 20, Koyama, 10]

サンプルコード

Java のsort とComparator のサンプル