
こんにちは。大城です。
本ブログでは、Java SE 8で追加されたStream APIについて、初心者向けに解説していきます。前回のブログでは、2重Listを1重に直すflatMapと重複を削除するdistinctについて説明しました。
中間処理3回目の今回は、ソートを行うsortedについて解説していきます。
環境
- OS
- Windows10
- Java
- Java8
Comparableを実装しているオブジェクトをソートするsorted()
IntegerやStringのような、java.lang.Comparableを実装しているクラスは簡単にソートすることができます。例をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class Main { public static void main(String[] args) { List<Integer> intList = Arrays.asList(3, 1, 4, 5); System.out.println("------ ソートする前 ------"); intList.stream() .forEach(e -> System.out.println(e)); System.out.println("------ sorted()メソッドによってソートした結果 ------"); intList.stream() .sorted() // ソートの実施 .forEach(e -> System.out.println(e)); List<String> strList = Arrays.asList("Tokyo", "Chiba", "Saitama", "Kanagawa", "Gunma"); System.out.println("------ ソートする前 ------"); strList.stream() .forEach(e -> System.out.println(e)); System.out.println("------ sorted()メソッドによってソートした結果 ------"); strList.stream() .sorted() // ソートの実施 .forEach(e -> System.out.println(e)); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
------ ソートする前 ------ 3 1 4 5 ------ sorted()メソッドによってソートした結果 ------ 1 3 4 5 ------ ソートする前 ------ Tokyo Chiba Saitama Kanagawa Gunma ------ sorted()メソッドによってソートした結果 ------ Chiba Gunma Kanagawa Saitama Tokyo |
Integerはその大きさで、Stringは辞書式順序でそれぞれソートされていることがわかります。このように、Comparableを実装しているクラスは、Streamを取得してsorted()メソッドを実行するだけでソートを実施することができます。
Comprableを実装していないオブジェクトのソート
続いて、自作クラスなどのようなComparableを実装していないクラスをソートするする方法について解説します。この場合は、オブジェクトからComparableな値を取り出して比較するComparatorを生成して、sortedに引数として渡します。例をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
class City { private String name; private int population; public City(String name, int population) { this.name = name; this.population = population; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } } public class Main { public static void main(String[] args) { List<City> cityList = new ArrayList<> (Arrays.asList( new City("Bunkyo-ku", 219724), new City("Taito-ku", 198073), new City("Chiyoda-ku", 58406), new City("Shinjuku-ku", 333560) )); System.out.println("------ ソートする前 ------"); cityList.stream() .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ nameで生成したComparatorでソートを実施 ------"); Comparator<City> nameComp = Comparator.comparing(e -> e.getName()); // CityクラスのプロパティnameによってComparatorを生成 cityList.stream() .sorted(nameComp) // nameで生成したComparatorでソートを実施 .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 |
------ ソートする前 ------ Bunkyo-ku :219724人 Taito-ku :198073人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 ------ nameで生成したComparatorでソートを実施 ------ Bunkyo-ku :219724人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 Taito-ku :198073人 |
Comparatorは、Comparator.comparing()にラムダ式を渡して生成します。この際、オブジェクトからComparableな値を返すようなラムダ式を渡します。上記の例ではCityクラスのString型のプロパティであるnameを返すラムダ式e -> e.getName()を渡しています。
これによって、Streamはnameプロパティによって辞書式にソートされる結果となっているのです。上記の他に、City.getName().length()や、City.getPopulation()もComparableな値を返すので、これらによるソートの例を下記に記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
class City { private String name; private int population; public City(String name, int population) { this.name = name; this.population = population; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } } public class Main { public static void main(String[] args) { List<City> cityList = new ArrayList<> (Arrays.asList( new City("Bunkyo-ku", 219724), new City("Taito-ku", 198073), new City("Chiyoda-ku", 58406), new City("Shinjuku-ku", 333560) )); System.out.println("------ ソートする前 ------"); cityList.stream() .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ nameによってソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> e.getName())) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ nameのlengthでソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> e.getName().length())) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ poplationでソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> e.getPopulation())) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
------ ソートする前 ------ Bunkyo-ku :219724人 Taito-ku :198073人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 ------ nameによってソートした結果 ------ Bunkyo-ku :219724人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 Taito-ku :198073人 ------ nameのlengthでソートした結果 ------ Taito-ku :198073人 Bunkyo-ku :219724人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 ------ poplationでソートした結果 ------ Chiyoda-ku :58406人 Taito-ku :198073人 Bunkyo-ku :219724人 Shinjuku-ku :333560人 |
逆順ソート
上記では昇順ソートについて説明しましたが、最後に降順ソートのやり方も紹介します。
Comparableなオブジェクトの場合
ComparableなオブジェクトはsortedにComparator.reverseOrder()を渡すことで降順ソートすることができます。例をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class Main { public static void main(String[] args) { List<Integer> intList = Arrays.asList(3, 1, 4, 5); System.out.println("------ ソートする前 ------"); intList.stream() .forEach(e -> System.out.println(e)); System.out.println("------ sorted(Comparator.reverseOrder())によって降順ソートした結果 ------"); intList.stream() .sorted(Comparator.reverseOrder()) // ソートの実施 .forEach(e -> System.out.println(e)); List<String> strList = Arrays.asList("Tokyo", "Chiba", "Saitama", "Kanagawa", "Gunma"); System.out.println("------ ソートする前 ------"); strList.stream() .forEach(e -> System.out.println(e)); System.out.println("------ sorted(Comparator.reverseOrder())によって降順ソートした結果 ------"); strList.stream() .sorted(Comparator.reverseOrder()) // ソートの実施 .forEach(e -> System.out.println(e)); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
------ ソートする前 ------ 3 1 4 5 ------ sorted(Comparator.reverseOrder())によって降順ソートした結果 ------ 5 4 3 1 ------ ソートする前 ------ Tokyo Chiba Saitama Kanagawa Gunma ------ sorted(Comparator.reverseOrder())によって降順ソートした結果 ------ Tokyo Saitama Kanagawa Gunma Chiba |
降順にソートできていることがわかります。
Comparableを実装しないオブジェクトの場合
Comparableが実装されていないオブジェクトは、Comparatorに.reversed()を指定します。例をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
class City { private String name; private int population; public City(String name, int population) { this.name = name; this.population = population; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } } public class Main { public static void main(String[] args) { List<City> cityList = new ArrayList<> (Arrays.asList( new City("Bunkyo-ku", 219724), new City("Taito-ku", 198073), new City("Chiyoda-ku", 58406), new City("Shinjuku-ku", 333560) )); System.out.println("------ ソートする前 ------"); cityList.stream() .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ nameによって降順ソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> ((City)e).getName()).reversed()) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ nameのlengthで降順ソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> ((City)e).getName().length()).reversed()) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); System.out.println("------ poplationで降順ソートした結果 ------"); cityList.stream() .sorted(Comparator.comparing(e -> ((City)e).getPopulation()).reversed()) .forEach(e -> System.out.println(e.getName() + "\t:" + e.getPopulation() + "人")); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
------ ソートする前 ------ Bunkyo-ku :219724人 Taito-ku :198073人 Chiyoda-ku :58406人 Shinjuku-ku :333560人 ------ nameによって降順ソートした結果 ------ Taito-ku :198073人 Shinjuku-ku :333560人 Chiyoda-ku :58406人 Bunkyo-ku :219724人 ------ nameのlengthで降順ソートした結果 ------ Shinjuku-ku :333560人 Chiyoda-ku :58406人 Bunkyo-ku :219724人 Taito-ku :198073人 ------ poplationで降順ソートした結果 ------ Shinjuku-ku :333560人 Bunkyo-ku :219724人 Taito-ku :198073人 Chiyoda-ku :58406人 |
それぞれ降順ソートができていることがわかります。注意点として、comparingに渡すラムダ式では((City)e).getName()のようにキャストを行うなどして明示的に型を指定しなければなりません。
詳細は割愛しますが、型を推論できる根拠がないとコンパイルエラーが発生します。
まとめ
いかがでしたか。
Streamのソートを行いたいときはsorted()を実行するだけで良く、非常にわかりやすいかと思います。次回では、Streamを用いた処理の略記やラムダ式・メソッド参照について解説していこうと思います。
それでは、また。
《関連記事》
- 今更聞けない?Java8の気になる機能3選
- 【Java Stream API 超入門】filterメソッドを使って、条件でコレクション要素をフィルタリングする方法
- 【Java Stream API 超入門】filterメソッドでの絞り込みとmapメソッドによる要素の変換
- 【Java Stream API 超入門】多重リストを纏めるflatMapと重複の削除を行うdistinct
- これさえ見ればもう怖くない! Javaでよく出るエラーと対策5選

