【Java入門】配列やListをソートする方法(文字列もソート)

こんにちは!フリーランスのオータケです。

Javaで配列やリストを扱う上でソート(並び替え)が必要になる場面があるかと思います。この記事では、配列(固定長)のソートとListのソートという基本的な内容から、

  • ComparatorでListをソートする場合
  • 文字列をソートする場合
  • 複数キーでソートする場合

などの応用的な使い方に関しても解説していきます。今回はソートについて、わかりやすく解説します!

なお、Javaの記事については、こちらにまとめています。

目次

配列(固定長)のソート

配列(固定長)をソートするには、Arrarsクラスのsortメソッドを使います。以下のように記述します。

Arrays.sort(配列名);

上記の記述では昇順に並び替えることができます。では降順に並び替えたい場合はどうすればいいでしょうか?CollectionsクラスのreverseOrderメソッドをsortメソッドの第2引数に指定します。

以下のような記述になります。

Arrays.sort(配列名,  Collections.reverseOrder());

reverseOrderメソッドは順序を逆にするコンパレータを返します。なお、コンパレータとは比較処理を行うクラスのためのインターフェースです。コンパレータについては後ほどくわしく解説します。

Collectionsクラスを使う場合は、ソートする配列にはInteger型などのクラス型を指定する必要があります。int型などのプリミティブ型を指定するとエラーが発生するので、注意しましょう。

昇順でソートする場合

それでは、昇順でソートする場合についてサンプルコードで確認しましょう。

import java.util.Arrays;

public class Main {
 
    public static void main(String[] args) {
        int[] foo = {10, 30, 5, 2, 11, 90};
         
        Arrays.sort(foo);
        
        for(int i : foo) {
            System.out.println(i);
        }
    }

}

実行結果:

2
5
10
11
30
90

降順でソートする場合

それでは、降順でソートする場合についてサンプルコードで確認しましょう。

import java.util.Arrays;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        Integer[] foo = {10, 30, 5, 2, 11, 90};
         
        Arrays.sort(foo, Collections.reverseOrder());
        
        System.out.println(Arrays.asList(foo));
    }

}

実行結果:

[90, 30, 11, 10, 5, 2]

このサンプルコードではCollectionsクラスを使用するため、配列の宣言時の型をint型ではなく、クラス型のInteger型にしています。

降順でソートするため、Arraysクラスのsortメソッドの第2引数はCollectionsクラスのreverseOrderメソッドを指定しています。

Listのソート

List型のオブジェクトの要素をソートするには、Collectionsクラスのsortメソッドを使用します。以下のように記述します。

Collections.sort(リスト名);

上記の記述では昇順に並び替えることができ、降順で並び替えるにはsortメソッドの第2引数にCollectionsクラスのreverseOrderメソッドを指定します。以下のように記述します。

Collections.sort(リスト名,  Collections.reverseOrder());

昇順でソートする場合

それでは、昇順でソートする場合についてサンプルコードで確認しましょう。

import java.util.ArrayList;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        ArrayList<Integer> foo = new ArrayList<>();
        
        foo.add(10);
        foo.add(30);
        foo.add(5);
        foo.add(2);
        foo.add(11);
        foo.add(90);
         
        Collections.sort(foo);
        
        System.out.println(foo);
    }

}

実行結果:

[2, 5, 10, 11, 30, 90]

降順でソートする場合

それでは、降順でソートする場合についてサンプルコードで確認しましょう。

import java.util.ArrayList;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        ArrayList<Integer> foo = new ArrayList<>();
        
        foo.add(10);
        foo.add(30);
        foo.add(5);
        foo.add(2);
        foo.add(11);
        foo.add(90);
         
        Collections.sort(foo, Collections.reverseOrder());
        
        System.out.println(foo);
    }

}

実行結果:

[90, 30, 11, 10, 5, 2]

ComparatorでListをソートする場合

今までのソート方法では文字列や数値型と言ったJava側で用意されている型をソートする方法を解説してきました。

しかし、自分で定義したクラスオブジェクトの特定の値を元にソートしたい場合や、更に細かい条件等でソートするにはどうすればいいでしょうか?

Comparatorインタフェースを用いることでこれを実現できます。これまでのサンプルコードでは、CollecttionsクラスのreverseOrderメソッドをsortメソッドの第2引数に指定して、降順に並べ替えることができました。

reverseOrderメソッドはコンパレータを返します。このコンパレータはComparatorインターフェースを実装するクラスで自作することができます。ここでは降順に並び替えるコンパレータを自作する場合の例をご紹介します。

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

public class Main {
 
    public static void main(String[] args) {
        ArrayList<Integer> foo = new ArrayList<>();
        
        foo.add(10);
        foo.add(30);
        foo.add(5);
        foo.add(2);
        foo.add(11);
        foo.add(90);
         
        Collections.sort(
            foo, 
            new Comparator<Integer>() {
                @Override
                public int compare(Integer obj1, Integer obj2) {
                    return obj2 - obj1;
                }
            }
        );
        
        System.out.println(foo);
    }

}

実行結果:

[90, 30, 11, 10, 5, 2]

このサンプルコードでは、Comparatorインターフェースを実装してreverseOrderメソッドと同じ処理を実行しています。一見するとコード量が多くなっただけじゃないかと思われる方もいるかもしれません。

しかし、Comparatorインターフェースを用いた方法ではソートするための条件をプログラマが決めることができます。複雑な条件でのソートやオブジェクトの並び替えを特定のルールに沿って行いたいときは、この方法を用いるといいでしょう。

複数の条件でのオブジェクトの並び替えの例を後ほどご紹介します。

Java8のラムダ式を使う方法

Java8の場合はStream APIとラムダ式でより短く書くことが可能です。

リスト名.stream().sorted((x, y) -> y - x);

こちらでくわしく解説していますので、ぜひ参考にしてください。

文字列をソートする場合

数値の配列やリストのように、文字列の配列やリストも並び替えたい場合ってありますよね。そんな場合は、これまでご紹介したArrays.sortメソッドやCollections.sortメソッドを使うことができます。

文字列を並び替える場合は、文字列の頭文字のアルファベット順や読み方の50音順で順序付けられます。それぞれの方法についてくわしく解説していきます。

Arrays.sortを使う方法

数値の配列の並べ替えと同じように、文字列の場合もArrars.sortを使うことができます。サンプルコードで確認しましょう。

import java.util.Arrays;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        String[] foo = {"melon", "orange", "apple"};
         
        Arrays.sort(foo);
        
        System.out.println(Arrays.asList(foo));
    }

}

実行結果:

[apple, melon, orange]

このサンプルコードでは、アルファベット文字列を要素に持つリストを並び替えています。文字列の頭文字のアルファベット順に並び替えられていることがわかります。

Collections.sortを使う方法

数値のリストの並べ替えと同じように、文字列の場合もCollections.sortを使うことができます。サンプルコードで確認しましょう。

import java.util.ArrayList;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        ArrayList<String> foo = new ArrayList<>();
        
        foo.add("melon");
        foo.add("orange");
        foo.add("apple");
         
        Collections.sort(foo);
        
        System.out.println(foo);
    }

}

実行結果:

[apple, melon, orange]

複数キーでソートする場合

複数のキーでソートする場合は、Comparatorインターフェースを実装した独自クラスでソートの条件を定義します。人物の年齢と名前でソートする場合について、サンプルコードで確認していきましょう。

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

class MyClass {
    private int age;
    private String name;
    
    public MyClass(int age, String name) {
        this.age = age;
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public String getName() {
        return name;
    }
}

class MyComp implements Comparator<MyClass> {
    public int compare(MyClass c1, MyClass c2) {
        if(c1.getAge() < c2.getAge()) {
            return -1;
        } else if(c1.getAge() > c2.getAge()) {
            return 1;
        } else {
            return c1.getName().compareTo(c2.getName());
        }
    }
}

public class Main {
 
    public static void main(String[] args) {
        ArrayList<MyClass> foo = new ArrayList<>();
        
        foo.add(new MyClass(30, "Nakamura"));
        foo.add(new MyClass(30, "Tanaka"));
        foo.add(new MyClass(20, "Yamashita"));
        foo.add(new MyClass(20, "Sato"));
        foo.add(new MyClass(40, "Takahashi"));
        foo.add(new MyClass(40, "Ito"));
         
        Collections.sort(foo, new MyComp());
        
        for(MyClass c : foo) {
            System.out.println(c.getAge() + ", " + c.getName());
        }
    }

}

実行結果:

20, Sato
20, Yamashita
30, Nakamura
30, Tanaka
40, Ito
40, Takahashi

このサンプルコードでは、まずint型変数ageとString型変数nameをメンバに持つMyClassクラスを定義しています。Comparatorインターフェースを実装したMyCompクラスではMyClassクラスのメンバageを第1キーにメンバnameを第2キーに指定して独自のコンパレータを定義しています。

この独自のコンパレータクラスを指定してCollections.sortメソッドでソートを行い、2つのキーで昇順にソートされていることがわかります。なお、サンプルコードのなかでcompareToメソッドを使って比較しています。

compareToメソッドについてば次の章でくわしく解説しています。

compareToで大小を比較する方法総まとめ

compareToメソッドで大小を比較するいろいろな方法を次の記事にまとめているので、ぜひ確認してください!

配列についてもっと詳しく知りたい!

配列についてもっと知りたい方はこちらもご覧ください!

まとめ

いかがだったでしょうか。ソートの方法はいくつかあるため少々分かりづらい面もありますが使い方はそこまで難しくないため使っていくことで慣れるのではないかと思います。

忘れてしまった場合は是非この記事を思い出して下さい!

この記事を書いた人

30歳、フリーランスプログラマ。中学の頃よりプログラミングに興味を持ちゲーム開発やWebサイト構築などを経験
新しいフレームワークやライブラリに興味があり革新的な機能が含まれていると泣いて喜ぶ。

目次