JavaJava関連

【Java】配列ソートを解説|昇順・降順・オブジェクト

Java配列ソート解説ページのアイキャッチ画像 Java

この記事では、Javaでの昇順・降順ソートから、部分的ソート、並列ソート、オブジェクト配列のソート、そしてカスタムComparatorを使用したソートまで、幅広いソート方法を紹介します。

配列ソートの特徴を比較

ソート方法特徴
昇順ソート配列を小さい順に並べ替える。デフォルトの並べ替え順で、通常の数値や文字列の並べ替えに適用される。
降順ソート配列を大きい順に並べ替える。オブジェクト型配列に適用でき、数値や文字列を降順に整列させるのに使用される。
部分的なソート配列の一部のみを指定した範囲で並べ替える。必要な範囲だけ並べ替えたい場合に便利で、指定したインデックスの区間にのみ適用される。
並列ソート並列処理を利用して配列をソートする。大規模データに適しているが、小規模データに対しては非効率になる場合がある。
オブジェクト配列のソートComparableComparator を使用して、オブジェクトの特定のフィールドを基準に並べ替える。
カスタムComparatorを使用したソートComparator を用いて柔軟なソート基準を指定する方法。匿名クラスやラムダ式で独自の並べ替え基準を定義することができる。

昇順ソート

Java標準ライブラリのArrays.sort()メソッドを使用すると、簡単に昇順ソートができます。

Java
import java.util.Arrays;

public class Main {
	public static void main(String[] args) {
		int[] numbers = { 5, 2, 8, 1, 9 };
		Arrays.sort(numbers);
		System.out.println(Arrays.toString(numbers));
	}
}

実行結果

[1, 2, 5, 8, 9]

コードの解説

  • 配列の作成:
    • int[] numbers = {5, 2, 8, 1, 9}; この配列には、5つの整数が含まれています。これらの整数はランダムな順序で並んでいます。
  • ソートの実行:
    • Arrays.sort() メソッドを使用して、この配列をソートします。
    • このメソッドを呼び出すことで、配列 numbers の要素が昇順に並び替えられます。
  • ソート結果の表示:
    • Arrays.toString() メソッドを使用して配列を文字列として出力します。

文字列のコード例

Java
// String 型の配列を作成
String[] names = {"Charlie", "Alice", "Bob", "Eve"};

// 昇順でソート
Arrays.sort(names);
        
// 結果を表示
System.out.println( Arrays.toString(names));
[Alice, Bob, Charlie, Eve]

降順ソート

Javaで基本型の配列を降順にソートする方法はいくつかありますが、Arrays.sort() メソッドと Collections.reverseOrder() を組み合わせるのが一般的です。

※この方法は Integer などのラッパークラスの配列に対してのみ適用できる点です。基本データ型の配列(例えば、int[])には直接適用できません。

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

public class Main {
	public static void main(String[] args) {
		Integer[] numbers = { 5, 2, 8, 1, 9 };

		// 降順にソート
		Arrays.sort(numbers, Collections.reverseOrder());

		// ソート結果の表示
		System.out.println(Arrays.toString(numbers));
	}
}

実行結果:

[9, 8, 5, 2, 1]

元の配列の要素が {5, 2, 8, 1, 9} でしたが、降順にソートされた結果は {9, 8, 5, 2, 1} となります。


コード解説

  • 配列の作成:
    • 整数の配列 numbers を作成し、いくつかの整数を初期化します。この配列は Integer 型であることに注意してください。
  • 降順ソートの実行:
    • Arrays.sort(numbers, Collections.reverseOrder()) メソッドを使用して、配列を降順にソートします。このメソッドは、内部で昇順にソートした後、要素を逆順に並べ替えます。
  • 結果の表示:
    • ソート後、System.out.println() メソッドを使用して、ソートされた配列の内容を表示します。

文字列のコード例

Java
// String 型の配列を作成
String[] names = {"Charlie", "Alice", "Bob", "Eve"};

// 降順でソート
Arrays.sort(names, Collections.reverseOrder());
        
// 結果を表示
System.out.println(Arrays.toString(names));
[Eve, Charlie, Bob, Alice]

部分的なソート

配列の一部分だけをソートしたい場合、Arrays.sort()メソッドのオーバーロードバージョンを使用します。

Java
import java.util.Arrays;

public class Main {
	public static void main(String[] args) {
		int[] numbers = { 5, 2, 8, 1, 9, 3, 7 };
		Arrays.sort(numbers, 2, 5);
		System.out.println(Arrays.toString(numbers));
	}
}

実行結果:

[5, 2, 1, 8, 9, 3, 7]

この例では、インデックス2から4(5未満)までの要素がソートされています。


コード解説

  • 配列の作成:
    • 上記のコードでは、配列 numbers{5, 2, 8, 1, 9, 3, 7} という値で初期化されています。
  • 部分的なソートの実行:
    • Arrays.sort(numbers, 2, 5) メソッドを使用して、インデックス 2 から 4(5未満)までの要素をソートします。この場合、ソート対象は {8, 1, 9} になります。

並列ソート

Java 8で導入された Arrays.parallelSort() メソッドを使用すると、マルチスレッドでソートを行い、大規模な配列に対してパフォーマンスを向上させることができます。

Java
import java.util.Arrays;

public class Main {
	public static void main(String[] args) {
		int[] largeArray = new int[1000000];

		// 配列にランダムな値を設定
		for (int i = 0; i < largeArray.length; i++) {
			largeArray[i] = (int) (Math.random() * 1000000); // 0から999999のランダムな整数
		}

		// 並列ソートを実行
		Arrays.parallelSort(largeArray);

		// 結果の一部を表示
		System.out.println(Arrays.toString(Arrays.copyOf(largeArray, 10))); // 最初の10個の要素を表示
	}
}

実行結果:

[0, 1, 4, 4, 8, 8, 10, 10, 12, 13]

※実際の数字はランダムに生成されるため、毎回異なる結果になります。


コード解説

  • 配列の作成:
    • 1,000,000要素を持つ整数型の配列 largeArray を作成します。
  • 値の設定:
    • ループを使用して、配列にランダムな整数値を設定しています。ここでは、0から999,999までのランダムな整数を生成しています。
  • 並列ソートの実行:
    • Arrays.parallelSort(largeArray) メソッドを呼び出すことで、配列を並列にソートします。このメソッドは、内部で複数のスレッドを利用して、ソートを行います。
  • 結果の一部を表示:
    • System.out.println(Arrays.toString(Arrays.copyOf(largeArray, 10))); // 最初の10個の要素を表示しています。
    • 配列が大きいため、全ての要素を表示すると非常に長くなります。そこで、最初の10個の要素を表示しています。

オブジェクト配列のソート

オブジェクトの配列をソートする場合、そのオブジェクトがComparableインターフェースを実装している必要があります。

Java
import java.util.Arrays;

// Person クラスは Comparable インターフェースを実装し、年齢で比較可能にします
class Person implements Comparable<Person> {
    String name;  // 名前を格納するフィールド
    int age;      // 年齢を格納するフィールド

    // コンストラクタで名前と年齢を初期化
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // compareTo メソッドをオーバーライドし、年齢で比較する
    @Override
    public int compareTo(Person other) {
        return this.age - other.age;  // 年齢を基準に昇順でソート
    }

    // toString メソッドをオーバーライドして、名前と年齢を返す
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

// メインクラス
public class Main {
    public static void main(String[] args) {
        // Person オブジェクトの配列を作成
        Person[] people = {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        };
        
        // 配列を年齢でソート
        Arrays.sort(people);
        
        // ソート後の配列を表示
        System.out.println(Arrays.toString(people));
    }
}

実行結果:

[Bob (25), Alice (30), Charlie (35)]

コード解説

Comparable インターフェースの実装:

Java
//Person クラスは Comparable インターフェースを実装し、年齢で比較可能にします
class Person implements Comparable<Person> {
	String name; // 名前を格納するフィールド
	int age; // 年齢を格納するフィールド

	// コンストラクタで名前と年齢を初期化
	Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// compareTo メソッドをオーバーライドし、年齢で比較する
	@Override
	public int compareTo(Person other) {
		return this.age - other.age; // 年齢を基準に昇順でソート
	}

	// toString メソッドをオーバーライドして、名前と年齢を返す
	@Override
	public String toString() {
		return name + " (" + age + ")";
	}
}
  • フィールド:
    • name: 人の名前を格納する文字列型のフィールドです。
    • age: 人の年齢を格納する整数型のフィールドです。
  • コンストラクタ:
    • Person クラスのインスタンスを作成する際に、名前と年齢を受け取り、フィールドに初期化します。
  • compareTo メソッド:
    • このメソッドでは、現在のオブジェクト (this) と他のオブジェクト (other) を比較します。ここでは、年齢を基準にソートしています。this.age - other.age の結果が負であれば thisother よりも小さい(つまり、年齢が若い)ことを意味します。
  • toString メソッド:
    • このメソッドはオブジェクトを文字列として表示する際の形式を定義します。ここでは、名前と年齢を表示する形式にしています。

オブジェクト配列の作成とソート:

Java
// メインクラス
public class Main {
    public static void main(String[] args) {
        // Person オブジェクトの配列を作成
        Person[] people = {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        };
        
        // 配列を年齢でソート
        Arrays.sort(people);
        
        // ソート後の配列を表示
        System.out.println(Arrays.toString(people));
    }
}
  • 配列の作成: ここでは、Person クラスのインスタンスを3つ作成し、people 配列に格納しています。
  • ソートの実行: Arrays.sort(people) メソッドを呼び出すことで、配列 people の要素が年齢の昇順にソートされます。
ポイント

compareToメソッドは、オブジェクト間の比較方法を定義するだけで、ソート自体は行いません。実際のソート処理はArrays.sort()が行い、ソート時にcompareToを参照して、定義された基準(ここでは年齢の昇順)で並べ替えます。

カスタムComparatorを使用したソート

Comparatorインターフェースを実装することで、ソートの基準をカスタマイズできます。

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

// Person クラス
class Person {
    String name;  // 名前を格納するフィールド
    int age;      // 年齢を格納するフィールド

    // コンストラクタで名前と年齢を初期化
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // toString メソッドをオーバーライドして、名前と年齢を返す
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class Main {
    public static void main(String[] args) {
        // Person オブジェクトの配列を作成
        Person[] people = {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35),
            new Person("David", 25),
            new Person("Eve", 30)
        };

        // 年齢でソートする Comparator
        Comparator<Person> ageComparator = new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return Integer.compare(p1.age, p2.age); // 年齢で比較
            }
        };

        // 名前でソートする Comparator
        Comparator<Person> nameComparator = new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p1.name.compareTo(p2.name); // 名前で比較
            }
        };

        // 年齢でソート
        Arrays.sort(people, ageComparator);
        System.out.println("年齢でソート: " + Arrays.toString(people));

        // 名前でソート
        Arrays.sort(people, nameComparator);
        System.out.println("名前でソート: " + Arrays.toString(people));
    }
}

実行結果:

年齢でソート: [Bob (25), David (25), Alice (30), Eve (30), Charlie (35)]
名前でソート: [Alice (30), Bob (25), Charlie (35), David (25), Eve (30)]

Personクラスの解説

Java
// Person クラス
class Person {
    String name;  // 名前を格納するフィールド
    int age;      // 年齢を格納するフィールド

    // コンストラクタで名前と年齢を初期化
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // toString メソッドをオーバーライドして、名前と年齢を返す
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}
  • フィールド:
    • name: 人の名前を格納する文字列型のフィールドです。
    • age: 人の年齢を格納する整数型のフィールドです。
  • コンストラクタ:
    • Person クラスのインスタンスを作成する際に、名前と年齢を受け取り、フィールドに初期化します。
  • toStringメソッド:
    • オブジェクトを文字列として表示する際の形式を定義しています。このメソッドをオーバーライドすることで、System.out.println などで表示するときに名前と年齢をわかりやすく出力します。

Mainクラスの解説

Java
public class Main {
    public static void main(String[] args) {
        // Person オブジェクトの配列を作成
        Person[] people = {
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35),
            new Person("David", 25),
            new Person("Eve", 30)
        };

        // 年齢でソートする Comparator
        Comparator<Person> ageComparator = new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return Integer.compare(p1.age, p2.age); // 年齢で比較
            }
        };

        // 名前でソートする Comparator
        Comparator<Person> nameComparator = new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p1.name.compareTo(p2.name); // 名前で比較
            }
        };

        // 年齢でソート
        Arrays.sort(people, ageComparator);
        System.out.println("年齢でソート: " + Arrays.toString(people));

        // 名前でソート
        Arrays.sort(people, nameComparator);
        System.out.println("名前でソート: " + Arrays.toString(people));
    }
}
  • 配列の作成:
    • Person クラスのインスタンスを複数作成し、people 配列に格納しています。この配列には、異なる名前と年齢を持つ5人の Person オブジェクトが含まれています。
  • Comparatorの定義:
    • ageComparator:
      年齢で Person オブジェクトを比較するための Comparator を定義しています。Integer.compare(p1.age, p2.age) を使用して、年齢の昇順に比較しています。
    • nameComparator:
      名前で Person オブジェクトを比較するための Comparator を定義しています。p1.name.compareTo(p2.name) を使用して、名前のアルファベット順に比較しています。
  • ソートの実行:
    • Arrays.sort(people, ageComparator) を呼び出すことで、people 配列が年齢の昇順にソートされます。
    • 同様に、Arrays.sort(people, nameComparator) を呼び出すことで、people 配列が名前のアルファベット順にソートされます。

ComparableインターフェースとComparatorインターフェースの違い

特徴ComparableComparator
目的自分自身と他のオブジェクトを比較するためのメソッド compareTo を提供複数の異なるソート基準を提供するためのメソッド compare を持つ
実装方法クラス自体が Comparable インターフェースを実装し、compareTo メソッドをオーバーライド別のクラス、無名クラス、またはラムダ式として実装
順序の定義クラス内で自然な順序を定義外部でオブジェクトを比較する
使用シーン1つの自然な順序が存在する場合(例:年齢、名前のアルファベット順)複数のソート基準が必要な場合(例:年齢での昇順や名前での昇順)

まとめ

  • 昇順ソートは要素を小さい順から大きい順に並べ替え、降順ソートはその逆順に並べ替えます。
  • 部分的なソートでは配列の特定の範囲のみをソートすることができます。
  • 並列ソートは大規模なデータセットに対して効率的なソートを実現します。
  • オブジェクト配列のソートでは、複雑なデータ構造を持つオブジェクトを特定の基準でソートできます。
  • カスタムComparatorを使用することで、独自の比較ロジックに基づいたソートが可能になります。

Javaのソート機能は、データ処理において非常に重要な役割を果たします。基本的なソートアルゴリズムの理解から始まり、より複雑なデータ構造や大規模なデータセットに対応するための高度な技術まで、幅広い知識が求められます。

未経験でもWEBスキルを取得したい方
  • Javaコース
    Javaプログラミングを基礎から応用まで、体系的に学べる実践的なカリキュラムが特徴です。「マインクラフト」を通じてJavaの基本文法とフレームワークの概念を学びます。また、実際のプロジェクト開発を通じて、データベース連携やWebアプリケーション開発のスキルを身につけることができます。

コメント

タイトルとURLをコピーしました