この記事では、Javaで複数の値をまとめて管理するListクラスで、ソートを行う方法を解説します。
JavaのListとは?
Listは複数の要素を入れるための入れ物
JavaのListは大きさが決まっていない配列のようなものとイメージしてください。Listは複数の値をまとめて管理する時に使用します。
複数の値を格納できるという意味では配列も同じですが、配列とListの違いは、Listに格納できるデータは参照型のみです。
LIstの基本的な使い方は、以下の記事で解説していますので、こちらもご覧ください。
【関連記事】
▶【Java入門】ArrayListの使い方!配列との違いも解説
要素は基本は追加した順に並ぶ
Listは、add メソッドで要素を追加することができます。追加した要素はソートしない限り、追加した順番に並んでいます。
次のコードは、Listに200 → 100の順に要素を追加し、コンソールにListの内容を出力しています。実行結果を見ても分かる通り、addメソッドで追加した順に、List内の要素が並んでいます。
List<Integer> 変数名 = new ArrayList<Integer>(); 変数名.add(200); 変数名.add(100); System.out.println(変数名);
実行結果:[200, 100]
数値のListをソートする方法
ここからはListの要素をソートする方法を解説していきます。最初は数値のListをソートする方法を見ていきましょう。
Listをソートする時は、Collectionsクラスのsort メソッドを使用します。以下に昇順/降順でソートする方法を、それぞれ解説します。
昇順でソートする
まずは、昇順でソートする場合のサンプルコードです。次のコードでは、ArrayListにaddメソッドで順不同に数値を追加し、最後にCollectionsクラスのsort メソッドでソートを実行しています。
import java.util.ArrayList; import java.util.Collections; import java.util.List; public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(40); list.add(100); list.add(20); list.add(50); list.add(10); Collections.sort(list); //昇順でListをソート System.out.println(list); }
実行結果:[10, 20, 40, 50, 100]
降順でソートする
続いて、降順でソートを行う方法を見ていきましょう。降順でソートするには、sortメソッドの第2引数にCollections.reverseOrder()メソッドを指定します。
List<Integer> list = new ArrayList<Integer>(); list.add(40); list.add(100); list.add(20); list.add(50); list.add(10); Collections.sort(list, Collections.reverseOrder()); //降順でListをソート System.out.println(list);
実行結果:[100, 50, 40, 20, 10]
配列も同じような書き方でソートできる
少し話は変わりますが、配列でもListと同じような書き方でソートが行えます。
Integer[] array = {40, 100, 20, 50, 10}; Arrays.sort(array); //昇順でソート Arrays.sort(array, Collections.reverseOrder()); //降順でソート
文字列のListをソートする方法
先述した数値のListをソートする時と同じように、Collectionsクラスのsort メソッドを使って、文字列(String)を格納したListをソートできます。
List<String> list = new ArrayList<String>(); list.add("Google"); list.add("Apple"); list.add("Microsoft"); Collections.sort(list); //昇順でListをソート System.out.println(list);
実行結果:[Apple, Google, Microsoft]
文字列は文字コード順にソートされる
文字列のソートでは、要素は文字コード順で並び替えられます。コンピューターの世界では、文字1つ1つに対し数値のコードが割り当てられており、文字列のソートは、この数値のコード順で並びます。
数字・アルファベット・ひらがな・カタカナなどについては、皆さんがイメージする通り(アルファベットであればA→Zの順)に文字コードが割り振られている為、ソート結果もイメージ通りになるでしょう。
ただし、漢字については「読み」の順でソートされるイメージを持つ方が多いと思いますが、Javaのデフォルトで使用されるUnicodeでは、漢字は「部首画数順」に文字が収録されています。
例えば、漢数字をソートすると以下のような結果になり、イメージ通りではないことが分かると思います。
[一, 七, 三, 九, 二, 五, 八, 六, 四]
Memo
Unicodeに収録されている漢字の一覧は、以下のサイトで確認することができます。興味のある方は一度ご覧になってみてください。
CJK統合漢字-全漢字一覧 (http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/cjku_klist.html)
クラスのListをソートする方法
独自に作成したクラスや、複数の条件でソートする場合、Comparatorインターフェースを実装したクラスを作成し、そこに任意のソート条件を書いていきます。
実際に独自に作成したクラスをソートするサンプルコードを見ていきましょう。次のコードは、商品名と金額を持つProductクラスと、Productクラスを金額の順にソートするための、ProductComparatorを実装した例です。
【Productクラス】
public class Product { private String name; //商品名 private int price; //金額 public Product(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public int getPrice() { return price; } }
【ProductComparatorクラス】
import java.util.Comparator; public class ProductComparator implements Comparator<Product> { public int compare(Product p1, Product p2) { //金額を比較 int compareResult = Integer.compare(p1.getPrice(), p2.getPrice()); //金額が同じ場合、商品名を比較 if (compareResult == 0) { compareResult = p1.getName().compareTo(p2.getName()); } return compareResult; } }
【ProductComparatorを使ってソートするコード】
List<Product> list = new ArrayList<>(); list.add(new Product("Pen", 100)); list.add(new Product("Pencil case", 2000)); list.add(new Product("Eraser", 100)); Collections.sort(list, new ProductComparator()); for(Product p : list) { System.out.printf("name=%s, price=%d\n", p.getName(), p.getPrice()); }
実行結果: name=Eraser, price=100 name=Pen, price=100 name=Pencil case, price=2000
Java8以降のラムダ式でソートする方法
Java8以降は、Stream APIとラムダ式でより短くソート処理を書くことが可能です。Comparatorインターフェイスでソート条件を書く場合、ソート条件の数だけクラスが増えていきますが、Java8以降で使えるラムダ式では、そんな必要がなくなりました。
上で解説したProductクラスをソートする処理を、ラムダ式に書き直したものが、以下のサンプルコードです。
List<Product> list = new ArrayList<>(); list.add(new Product("Pen", 100)); list.add(new Product("Pencil case", 2000)); list.add(new Product("Eraser", 100)); list.stream().sorted((p1, p2) -> { int ret = Integer.compare(p1.getPrice(), p2.getPrice()); return ret == 0 ? p1.getName().compareTo(p2.getName()) : ret; });
ラムダ式で書くと、Comparatorインターフェースを実装したクラスを用意する必要がないため、だいぶスッキリしました。
まとめ
JavaのListをソートする方法について解説しました。ListはJavaの開発では必ずと言っていいほど、よく使います。また、Listのソートを活用すると、複雑だったコードが簡潔に書ける場合もあります。
Listのソート方法をマスターして、Javaの知識を向上させましょう。