JavaJava関連

【Java】配列の検索|メソッドを解説

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

この記事では、Javaにおける配列の検索方法を解説します。Arrays.binarySearch()、Arrays.equals()、Stream APIのfilter()とfindFirst()、anyMatch()、従来のfor文を使用した検索方法など、様々なアプローチを紹介します。

配列の検索|メソッドの比較

メソッド使用場面特徴
Arrays.binarySearch()ソート済みの配列で特定の要素を高速に検索する場合二分探索アルゴリズムを使用するため、大規模なソート済み配列で効率的
Arrays.equals()2つの配列の内容が完全に一致するかを確認する場合配列の長さと各要素を順番に比較
Arrays.stream().filter()特定の条件に合う要素をすべて抽出する場合複雑な条件での検索が可能、Stream APIの他のメソッドと組み合わせて使用可能
Arrays.stream().anyMatch()条件に合う要素が1つでも存在するかを確認する場合条件に合う要素が見つかった時点で処理を終了するため効率的
Arrays.stream().findFirst()条件に合う最初の要素のみを取得する場合Optional型で結果を返すため、要素が存在しない場合の処理が容易
for文による検索単純な検索や、配列の全要素に対して処理を行う場合カスタマイズ性が高く、複雑な条件での検索も可能

Arrays.binarySearch()

JavaのArraysクラスで提供されるバイナリサーチ(二分探索)メソッドbinarySearchを使用して、特定のキー(key)のインデックスを検索する例です。

Java
import java.util.Arrays;

public class BinarySearchExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        int key = 3;
        int index = Arrays.binarySearch(numbers, key);
        System.out.println("Index of " + key + ": " + index);
    }
}

実行結果:

Index of 3: 2

keyである3のインデックスが2であることを示しています(Javaの配列は0から始まるため、3は配列の3番目の要素でインデックスは2になります)。

解説:

  • int[] numbers = {1, 2, 3, 4, 5};
    • この配列には{1, 2, 3, 4, 5}の順序で要素が格納されています。バイナリサーチを行うためには配列が昇順にソートされている必要がありますが、ここではすでに昇順で定義されています。
  • int key = 3;
    • keyという変数には、探したい要素(今回は3)が格納されています。このkeyが、配列内でのインデックス位置を検索する対象です。
  • int index = Arrays.binarySearch(numbers, key);
    • Arrays.binarySearchメソッドを使用して、numbers配列からkeyの位置を検索しています。バイナリサーチアルゴリズムは、配列が昇順に並んでいることを前提に、配列の中央要素とkeyを比較し、探索範囲を半分に絞り込む方式で効率的に検索を行います。
    • binarySearchメソッドは、keyが配列に存在する場合、そのインデックスを返します。
    • keyが存在しない場合は、負の値が返されるため、結果から要素の存在を確認することも可能です。

Arrays.equals()

JavaのArraysクラスが提供するequalsメソッドを使用して、2つの配列が等しいかどうかを比較する例です。

Java
import java.util.Arrays;

public class EqualsExample {
    public static void main(String[] args) {
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};
        int[] array3 = {1, 2, 4};

        boolean isEqual1 = Arrays.equals(array1, array2);
        boolean isEqual2 = Arrays.equals(array1, array3);

        System.out.println("array1 equals array2: " + isEqual1);
        System.out.println("array1 equals array3: " + isEqual2);
    }
}

実行結果:

array1 equals array2: true
array1 equals array3: false
  • array1array2が等しいかどうかの結果がisEqual1として出力されます。
  • 同様に、array1array3が等しいかどうかの結果がisEqual2として出力されます。

解説:

int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = {1, 2, 4};

ここでは、3つの整数配列array1array2、およびarray3を定義しています。

  • array1array2は同じ要素を持つため、等しいと判断されるべき配列です。
  • array3array1array2と一部異なる要素(最後の値が4)を持っているため、等しくないと判断されるはずです。
boolean isEqual1 = Arrays.equals(array1, array2);
boolean isEqual2 = Arrays.equals(array1, array3);

ここで、Arrays.equalsメソッドを使ってarray1array2、およびarray1array3等価性をそれぞれ判定しています。

  • Arrays.equalsメソッドは、2つの配列の長さが同じであり、かつ各要素が同じ位置で同じ値である場合にtrueを返します。
  • 1つでも異なる要素がある場合、falseを返します。

したがって、isEqual1にはtrueが、isEqual2にはfalseが格納されるはずです。

Stream API: filter() と findFirst()

Stream APIfilterfindFirstメソッド を使って、特定の条件を満たす要素を効率的に検索する例です。また、結果を安全に処理するためにOptionalを利用して、見つからなかった場合のnullを避けています。

Java
import java.util.Arrays;
import java.util.Optional;

public class StreamExample {
    public static void main(String[] args) {
        String[] fruits = {"apple", "banana", "orange", "grape"};

        Optional<String> result = Arrays.stream(fruits)
                                        .filter(s -> s.startsWith("a"))
                                        .findFirst();

        System.out.println("First fruit starting with 'a': " + result.orElse("Not found"));
    }
}

実行結果:

First fruit starting with 'a': apple

配列の最初の要素である"apple""a"で始まるため、"apple"が結果として表示されます。
もし、配列内に"a"で始まる要素が1つもなければ、orElseによって"Not found"が表示されます。

解説:

String[] fruits = {"apple", "banana", "orange", "grape"};

ここでは、fruitsという名前の文字列配列を定義しています。この配列には4つのフルーツの名前が格納されています。

Optional<String> result = Arrays.stream(fruits)
                                .filter(s -> s.startsWith("a"))
                                .findFirst();

この行では、以下のステップでStream APIを使って配列内の要素を操作しています。

  1. Arrays.stream(fruits)
    この部分で、Arraysクラスのstreamメソッドを使用して、fruits配列からストリームを作成します。ストリームは、データを順次処理するためのデータ構造で、配列やリストに対してシーケンシャルな操作を行うことができます。
  2. filter(s -> s.startsWith("a"))
    ストリームに対してフィルタ処理を行います。filterメソッドはラムダ式を受け取り、指定された条件(ここでは"a"で始まる文字列)を満たす要素だけを残します。この例では、フルーツの名前が"a"で始まるかどうかを確認し、条件を満たす要素のみをストリームに残します。
  3. findFirst()
    filterを通過したストリームの要素のうち、最初の1つを取得します。結果はOptionalオブジェクトとして返されます。Optionalを使用することで、結果が見つからなかった場合のnull回避ができます。
System.out.println("First fruit starting with 'a': " + result.orElse("Not found"));

この行で、結果をコンソールに出力しています。

  • result.orElse("Not found")を使って、Optionalの中身が存在する場合はその値を返し、存在しない場合には"Not found"を表示します。このようにOptionalを利用することで、nullが返ってくる場合の処理も簡潔に記述できます。

Stream API: anyMatch()

このコードは、JavaのStream APIanyMatchメソッドを使って、配列に特定の条件を満たす要素が少なくとも1つ存在するかを判定する例です。

Java
import java.util.Arrays;

public class AnyMatchExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};

        boolean hasEven = Arrays.stream(numbers).anyMatch(n -> n % 2 == 0);
        boolean hasGreaterThan10 = Arrays.stream(numbers).anyMatch(n -> n > 10);

        System.out.println("Has even number: " + hasEven);
        System.out.println("Has number greater than 10: " + hasGreaterThan10);
    }
}

実行結果:

Has even number: true
Has number greater than 10: false
  • hasEventrueの場合、「Has even number: true」が表示され、偶数が含まれていることがわかります。
  • hasGreaterThan10falseの場合、「Has number greater than 10: false」が表示され、10より大きい数が配列内にないことがわかります。

解説:

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

ここでは、numbersという名前の整数配列を定義しています。この配列には1から5までの整数が格納されています。

boolean hasEven = Arrays.stream(numbers).anyMatch(n -> n % 2 == 0);
boolean hasGreaterThan10 = Arrays.stream(numbers).anyMatch(n -> n > 10);

このの2行では、Stream APIを使ってnumbers配列に特定の条件を満たす要素が含まれているかをチェックしています。

  1. Arrays.stream(numbers)
    ここで、numbers配列をストリームに変換します。ストリームは、データを連続的に処理するためのAPIで、配列やリストに対してシーケンシャルな操作が可能です。
  2. anyMatch(n -> n % 2 == 0)
    最初のanyMatchメソッドは、配列内に少なくとも1つの偶数が含まれているかどうかを判定します。
    • anyMatchメソッドは、ストリームの要素が指定された条件を少なくとも1つ満たす場合にtrueを返します。条件を満たす要素がなければfalseが返されます。
    • ラムダ式 n -> n % 2 == 0は、要素nが2で割り切れるかどうかを判定する条件です。配列の中で偶数が見つかればhasEventrueが代入されます。
  3. anyMatch(n -> n > 10)
    2つ目のanyMatchメソッドは、配列内に10より大きい数が含まれているかどうかを判定します。
    • ラムダ式 n -> n > 10で、要素nが10より大きいかどうかを判定しています。この条件を満たす要素がなければ、hasGreaterThan10にはfalseが代入されます。

for文を使用した検索

このコードは、forループequalsメソッドを使って、文字列配列内に特定の文字列が存在するかどうかを調べ、存在する場合はそのインデックスも取得する例です。

Java
public class ForLoopSearchExample {
    public static void main(String[] args) {
        String[] countries = {"日本", "アメリカ", "イギリス"};
        String searchElement = "日本";
        boolean exist = false;
        int index = -1;

        for (int i = 0; i < countries.length; i++) {
            if (countries[i].equals(searchElement)) {
                exist = true;
                index = i;
                break;
            }
        }

        if (exist) {
            System.out.println(searchElement + " は配列内に存在し、インデックスは " + index + " です。");
        } else {
            System.out.println(searchElement + " は配列内に存在しません。");
        }
    }
}

実行結果:

日本 は配列内に存在し、インデックスは 0 です。
  • 配列countries内で、"日本"がインデックス0に存在するため、その位置が表示されます。

解説:

String[] countries = {"日本", "アメリカ", "イギリス"};

ここで、countriesという名前の文字列配列を定義し、3つの国の名前を格納しています。

  • "日本"
  • "アメリカ"
  • "イギリス"
String searchElement = "日本";
boolean exist = false;
int index = -1;

ここでは検索条件や結果を格納するための変数を定義しています。

  • searchElement には、検索対象の文字列 "日本" を指定しています。
  • exist は検索対象の要素が配列に存在するかどうかを示すフラグです。初期値はfalseで、検索で見つかった場合にtrueに更新されます。
  • index は検索対象の文字列が見つかった場合のインデックス(位置)を格納するための変数です。初期値を -1 とし、要素が見つかった場合にインデックス番号が代入されます。
for (int i = 0; i < countries.length; i++) {
    if (countries[i].equals(searchElement)) {
        exist = true;
        index = i;
        break;
    }
}

ここで、forループを使って配列内の要素を1つずつ確認しています。

  • for (int i = 0; i < countries.length; i++)
    iをインデックスとして0からcountries.length - 1までループを回します。countries.lengthは配列の要素数を取得します。
  • if (countries[i].equals(searchElement))
    各要素countries[i]が、検索対象のsearchElement等しいかどうかを確認します。
  • equalsメソッドは、2つの文字列が同じ内容かどうかをチェックするメソッドです。
  • 条件が一致した場合、existtrueに設定し、indexに現在のインデックスiを代入してbreakでループを終了します。
if (exist) {
    System.out.println(searchElement + " は配列内に存在し、インデックスは " + index + " です。");
} else {
    System.out.println(searchElement + " は配列内に存在しません。");
}

existフラグを確認し、検索対象が見つかったかどうかに応じて結果を出力します。

  • if (exist)trueの場合、searchElementが配列内に存在し、そのインデックスを表示します。
  • elseでは、検索対象が見つからなかったことをメッセージで表示します。

まとめ

  • Arrays.binarySearch()ソート済みの配列に対して効率的な二分探索を行います。
  • Arrays.equals()配列全体の等価性を確認するのに適しています。
  • Stream APIのfilter()とfindFirst()複雑な条件での検索に柔軟に対応できます。
  • Stream APIのanyMatch()条件に合致する要素の存在確認に適しています。
  • 従来のfor文を使用した検索はシンプル直感的ですが、大規模データでは非効率な場合があります。

Javaにおける配列の検索方法は、状況や要件によって最適なアプローチが異なります。Arrays.binarySearch() は高速ですが、事前にソートが必要という制約があります。一方、Stream APIを使用した方法は、より複雑な検索条件に対応できる柔軟性があります。

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

コメント

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