読み込み中...

初心者向けJavaのcontainsメソッド!完全解説と実用例10選

初心者向けJavaのcontainsメソッド解説のイメージ Java
この記事は約30分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Javaのcontainsメソッドは、文字列やコレクションに目的の値が含まれるかをtrueまたはfalseで判定する検索用メソッドです。初心者がプログラミングで条件分岐を書くとき、containsの戻り値をifに渡せると、入力チェック、一覧検索、キーワード判定を短いコードで組み立てられます。

その一方で、Javaの文字列検索では大文字と小文字、nullArrayListHashSetの違いを外すと、期待と違う判定になりやすいです。完全解説として、使い方、注意点、カスタマイズまでをサンプルコード中心に整理します。

動作確認環境
  • Java 21 / OpenJDK 21
  • 標準ライブラリ: java.langjava.utiljava.util.stream
📖 この記事で学べること
  • String.containsCollection.containsの違い
  • 初心者が間違えやすいnullと大小文字の扱い
  • 複数キーワード、正規表現、Map検索の使い方
  • StreamPredicateを使った検索条件の作り方
  • containsメソッドを安全にカスタマイズする考え方

Javaのcontainsメソッドとは

結論から言えば、Javaのcontainsメソッドは「対象の中に指定した値が含まれるか」を調べるための判定処理です。文字列ならStringCharSequenceを含むか、リストならListが要素を含むかを調べ、戻り値はbooleanになります。

公式ドキュメントによれば、Stringクラスcontainsは指定された文字列シーケンスを含む場合にtrueを返します。そのため、Javaプログラミングで検索結果を条件分岐へ渡したい場面と相性がよい構造です。

containsメソッドの基本概念

これを文字列で使う場合、"Hello, world!".contains("world")は部分文字列の有無を判定すると理解できます。コレクションで使う場合、List<String>"banana"があるかを調べるため、同じcontainsメソッドでも対象型によって内部の比較方法が変わります。

その違いを早くつかむには、StringListSetMapを分けて見るのが現実的です。JavaのList型を学ぶと、containsequals比較に依存する場面も理解しやすくなります。

対象主なメソッド判定内容戻り値注意点
Stringcontains部分文字列を含むかboolean大小文字を区別
ArrayListcontains同じ要素を含むかbooleanequalsで比較
HashSetcontains集合に要素があるかbooleanhashCodeも影響
MapcontainsKeyキーがあるかbooleanキー検索向き
MapcontainsValue値があるかboolean値を走査しやすい
StreamanyMatch条件を満たす要素があるかboolean条件式で制御
Patternmatches正規表現に合うかboolean部分一致には書き方が必要

一方、Mapにはそのままのcontainsではなく、containsKeycontainsValueが用意されています。公式のMapインターフェースでも、キーと値を分けた検索として扱われます。

💡 Tips: containsメソッドは、存在確認のためのbooleanを返す処理として覚えると整理しやすくなると覚えるとよいでしょう。取得位置や一致件数が必要な場合は、indexOffiltercountなど別のAPIも候補になります。

基本的に、containsメソッドは「値を取り出す」処理ではなく「あるかどうかを知る」処理です。検索後に値そのものを使いたいなら、getfindFirstOptionalなどを組み合わせると、判定と取得の責務を分けられます。

containsメソッドの詳細な使い方

containsメソッドの使い方は、対象が文字列かコレクションかで読み方が変わりますが、これは押さえたい点です。サンプルコードでは最小単位の検索から始め、初心者がつまずきやすい大小文字とnullも同じ流れで確認します。

サンプルコード1:基本的な文字列の検索

具体的には、String型のtargetに検索語keywordが含まれるかを調べます。Javaの文字列検索で最も短い形なので、完全解説の入り口として押さえたいサンプルコードです。

public class Main {
    public static void main(String[] args) {
        String target = "Hello, world!";
        String keyword = "world";
        boolean result = target.contains(keyword);
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。targetの中にkeywordと同じ並びがあるため、containsの戻り値が真になります。

このとき、判定対象は単語の意味ではなく文字の連続です。そのため、worldの前後に記号や空白があっても、連続した並びが保たれていれば一致します。検索語の前後に余計な空白が混じる入力では、trimstripで整えてから判定すると読みやすい処理になると考えられます。

サンプルコード2:リスト内の要素の検索

その使い方をListへ移すと、文字列の一部ではなく要素そのものが検索対象になります。ArrayListに入れた値を判定するため、Javaのコレクション処理を学ぶ初心者にも扱いやすい例です。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>(Arrays.asList("apple", "banana", "cherry"));
        boolean result = fruits.contains("banana");
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。fruits"banana"という要素があるため、List.containsが真を返します。

ただし、Listのcontainsメソッドは部分一致ではありません。"ban"を渡しても"banana"の一部としては扱われないので、部分検索が必要なら各要素に対してString.containsを使います。リストの要素が独自クラスの場合は、equalsの実装が検索結果に影響すると言えるでしょう。

サンプルコード3:大文字・小文字を区別せずに検索

一方、JavaのString.containsは大文字と小文字を区別します。検索条件をゆるめたい場合は、対象と検索語をtoLowerCase()またはtoUpperCase()で同じ形にそろえてから判定します。

public class Main {
    public static void main(String[] args) {
        String target = "Hello, World!";
        String keyword = "WORLD";
        boolean result = target.toLowerCase().contains(keyword.toLowerCase());
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。targetkeywordを小文字へ変換してから比較するため、WorldWORLDの表記差が消えます。

このとき、言語ごとの大文字小文字変換を厳密に扱う用途ではLocaleの指定も検討します。英数字中心の検索なら十分な場面が多いものの、多言語入力では変換結果が想定と違う可能性があるのが基本です。特にユーザー名、メールアドレス、タグ検索では、保存時に正規化するか検索時に正規化するかを先に決めると、後続の処理が安定するのが基本です。

サンプルコード4:nullを考慮した検索方法

ただし、targetnullの状態でcontainsメソッドを呼ぶとNullPointerExceptionが発生します。検索語がnullの場合も扱いを決めておくと、入力値を受け取るプログラミングで例外を避けやすくなります。

public class Main {
    public static void main(String[] args) {
        String target = null;
        String keyword = "hello";
        boolean result = (target != null && keyword != null) && target.contains(keyword);
        System.out.println(result);
    }
}

結果: 期待される出力はfalseです。&&は左から評価されるため、target != nullが偽になった時点でtarget.contains(keyword)は呼ばれません。

この書き方は短いですが、条件が増えると読みにくくなります。そのため、業務用コードではisPresentのような補助メソッドへ切り出し、nullの扱いを一箇所に寄せる設計も有効です。初心者は&&の短絡評価を理解しておくと、containsメソッド以外の例外対策にも応用できます。

サンプルコード5:部分文字列での検索

これまでの文字列検索は、すべて部分文字列の存在確認として動きますし、これが一つの目安です。たとえば"Javaプログラミング""プログラミング"が含まれるかを調べる場合、Javaのcontainsメソッドは自然な選択になります。

public class Main {
    public static void main(String[] args) {
        String target = "Javaプログラミング";
        String substring = "プログラミング";
        boolean result = target.contains(substring);
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。substringの文字列がtargetの末尾側に連続して含まれているため、判定が真になります。

そのため、入力されたタグ、商品名、説明文の中に特定語が含まれるかを調べる処理へ応用できます。より複雑な条件が必要になったら、matchesPatternへ切り替えると整理しやすくなるのが目安です。完全一致、前方一致、後方一致、部分一致を混同しないことが、検索ロジックを読みやすく保つための要点になるのが目安です。

⚠️ 注意: containsは正規表現を解釈しません。".*Java.*"を渡してもパターンではなく通常の文字列として扱われるため、正規表現が必要な場合はmatchesPatternを使います。

containsメソッドの応用例

containsメソッドの応用では、単純な一致だけでなく、複数条件やデータ構造に合わせた判定が中心になります。JavaのプログラミングではStreamMap、正規表現を組み合わせると、検索処理の表現力が広がりますが、覚えておくと役立つでしょう。

サンプルコード6:リスト内の特定の条件を満たす要素の検索

一般に、リスト内の値そのものではなく「条件に合う要素があるか」を調べるなら、containsよりStream.anyMatchが読みやすくなります。Javaアノテーションのように要素へメタ情報が付く設計でも、条件判定の考え方は近いです。

import java.util.Arrays;
import java.util.List;

public class App {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        boolean exists = numbers.stream().anyMatch(num -> num > 3);
        System.out.println(exists);
    }
}

結果: 期待される出力はtrueです。numbersには45があり、num > 3を満たす要素が少なくとも一つ存在します。

このサンプルコードではcontainsメソッドそのものではなく、同じ存在判定を条件式で表しています。値の完全一致ならcontains、条件付き検索ならanyMatchと使い分けると、コードの意図が伝わりやすくなるのがポイントです。条件の結果が一件でもあればよいのか、すべて満たす必要があるのかで、anyMatchallMatchを選び分けますし、ここがポイントです。

サンプルコード7:文字列内の特定のパターンの検索

その延長として、文字列に複数の語が含まれるかを正規表現で調べる方法があります。matchesは文字列全体がパターンに合うかを判定するため、部分一致には前後へ.*を付けます。

public class App {
    public static void main(String[] args) {
        String sentence = "私はJavaとPythonが好きです。";
        boolean result = sentence.matches(".*Java.*") && sentence.matches(".*Python.*");
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。sentenceJavaPythonの両方が含まれるため、&&でつないだ判定が真になります。

ただし、固定文字列だけを調べるならcontainsメソッドのほうが単純です。正規表現は記号の意味を理解する必要があるため、初心者はcontainsで足りる条件かを先に確認すると混乱を減らせます。複数語をすべて含む条件なら&&、どれか一語でよい条件なら||を使うと意図が明確になるのが一般的です。

サンプルコード8:マップのキー・値の検索

一方、Mapはキーから値を取り出す構造なので、検索もcontainsKeycontainsValueに分かれます。キーを調べる処理は高速に扱われることが多く、値の検索は値全体を確認する設計になります。

import java.util.HashMap;
import java.util.Map;

public class App {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 100);
        map.put("banana", 200);
        map.put("cherry", 300);
        boolean hasAppleKey = map.containsKey("apple");
        boolean hasValue200 = map.containsValue(200);
        System.out.println("hasAppleKey: " + hasAppleKey);
        System.out.println("hasValue200: " + hasValue200);
    }
}

結果: 期待される出力はhasAppleKey: truehasValue200: trueです。mapにはappleというキーと200という値が登録されています。

このサンプルコードでは、containsメソッドの考え方をMap向けのAPIへ置き換えています。キーで引く用途ならcontainsKey、値の存在だけを知りたい用途ならcontainsValueを選びますし、ここを基本と考えるとよいでしょう。キーに対して値を取得したい場合は、containsKeyだけでなくgetgetOrDefaultも候補になるのがポイントです。

サンプルコード9:複数の検索キーワードを使用

これらの考え方は、複数キーワードの検索にもそのまま使えます。配列の各要素をforで取り出し、同じtextに対してcontainsを繰り返す構成です。

public class App {
    public static void main(String[] args) {
        String text = "Javaはプログラミング言語の一つであり、多くの企業で採用されています。";
        String[] keywords = {"Java", "プログラミング", "企業"};
        for (String keyword : keywords) {
            if (text.contains(keyword)) {
                System.out.println("テキストは " + keyword + " を含む");
            }
        }
    }
}

結果: 期待される出力は、Javaプログラミング企業の各語を含む行です。keywordsに入った語がすべてtextに存在するため、三行分の出力が想定されます。

この構成は入力チェックや禁止語チェックへ応用できます。ただし、キーワードが多い場合はList化してstream()を使うと、全件一致か一部一致かをallMatchanyMatchで表しやすくなるのが現実的です。検索語を外部ファイルから読む場合は、空文字や重複語を先に除くと判定の意味がぶれにくくなるのが一般的です。

サンプルコード10:高度なフィルタリングを伴う検索

具体的には、オブジェクトのプロパティを見ながら絞り込む処理でもcontainsメソッドを使えます。名前に特定文字が含まれるか、年齢が条件を満たすかをfilterにまとめる例です。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class App {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 25));
        people.add(new Person("Bob", 30));
        people.add(new Person("Charlie", 35));
        List<Person> filteredPeople = people.stream()
                .filter(p -> p.getName().contains("b") || p.getAge() >= 30)
                .collect(Collectors.toList());
        for (Person p : filteredPeople) {
            System.out.println(p);
        }
    }
}

class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() { return name; }
    public int getAge() { return age; }
    @Override
    public String toString() {
        return "Person{" + "name='" + name + ''' + ", age=" + age + '}'; 
    }
}

結果: 期待される出力はBobCharlieに対応するPerson情報です。Bobは年齢条件を満たし、CharliegetAge() >= 30に一致します。

ただし、getName().contains("b")は小文字のbだけを探します。Bobの先頭は大文字Bなので、この条件だけでは一致せず、年齢条件によって抽出される点が注意点です。

このような検索は、顧客一覧、商品一覧、設定一覧のフィルタリングに近い形です。Javaのオーバーライドを理解しておくと、toStringequalsの扱いも読みやすくなると整理できます。独自クラスの検索では、表示用のtoStringと同一性判定用のequalsを混同しないことも大切になります。

注意点と対処法

containsメソッドの注意点は、判定ルールが単純なぶん、前処理を省くと失敗しやすいところにあります。大文字と小文字、null、データ構造ごとの計算量を分けて確認すると、初心者でも安全な使い方へ近づけますし、ここがポイントです。

大文字・小文字の取り扱い

JavaのString.containsは、Hellohelloを別の文字列として扱います。ユーザー入力の検索では、この差が想定外のfalseにつながることがあります。

public class Main {
    public static void main(String[] args) {
        String str = "Hello World";
        System.out.println(str.contains("hello"));
        System.out.println(str.contains("Hello"));
    }
}

結果: 期待される出力は一行目がfalse、二行目がtrueです。helloは先頭の大小文字が違うため一致せず、Helloは同じ並びとして見つかります。

そのため、大小文字を無視したい検索では、比較前に両方の文字列を同じ形式へ変換します。Javaのエスケープ処理と同じく、文字列は見た目と内部表現を分けて考えると扱いやすくなると理解できます。

public class Main {
    public static void main(String[] args) {
        String str = "Hello World";
        System.out.println(str.toUpperCase().contains("HELLO".toUpperCase()));
    }
}

結果: 期待される出力はtrueです。str.toUpperCase()"HELLO".toUpperCase()を比較するため、大小文字の差を吸収できます。

この変換は検索前の正規化と考えられます。たとえば記事タイトル、ユーザー入力、ファイル名の検索では、保存された文字列の形と検索語の形がずれることがあるため、比較条件を明示すると読み手に意図が伝わりますが、これは押さえたい点です。

null値の取り扱い

一方、nullは空文字""とは別物です。nullの参照に対してメソッドを呼び出すと例外になるため、containsメソッドの前に入力値の有無を確認します。

public class Main {
    public static void main(String[] args) {
        String str = "Hello World";
        String search = null;
        if(search != null && str.contains(search)) {
            System.out.println("Found");
        } else {
            System.out.println("Not Found or search string is null");
        }
    }
}

結果: 期待される出力はNot Found or search string is nullです。search != nullが偽になるため、str.contains(search)は評価されません。

このような注意点は、フォーム入力や外部ファイルの読み込みで特に表れます。Objects.nonNullOptional、早期returnを使う設計もありますが、単純な分岐ではsearch != nullで十分な場合があります。検索対象のstrnullになり得るなら、str != nullを先に置く順序が必要になるのが現実的です。

特定のデータ構造における振る舞い

同じcontainsメソッドでも、ArrayListHashSetでは検索の考え方が異なると覚えるとよいでしょう。ArrayListは順に探す構造になりやすく、HashSetはハッシュ値を使った集合検索として扱われます。

import java.util.ArrayList;
import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        HashSet<Integer> hashSet = new HashSet<>();
        for (int i = 0; i < 100000; i++) {
            arrayList.add(i);
            hashSet.add(i);
        }
        long start = System.currentTimeMillis();
        arrayList.contains(99999);
        long end = System.currentTimeMillis();
        System.out.println("ArrayList: " + (end - start) + "ms");
        start = System.currentTimeMillis();
        hashSet.contains(99999);
        end = System.currentTimeMillis();
        System.out.println("HashSet: " + (end - start) + "ms");
    }
}

結果: 期待される出力はArrayList: ...msHashSet: ...msの二行です。時間値は環境や負荷で変わるため、固定の数値として扱わないのが適切です。

公式のCollectionインターフェースでは、コレクションが要素群を表す基盤として定義されています。そのため、Javaではデータ構造を選ぶ段階で検索頻度、重複可否、順序の必要性を合わせて考えます。

⚠️ 注意: 時間計測のサンプルコードは学習用です。System.currentTimeMillis()の値だけで性能を断定せず、実運用の判断ではJVMのウォームアップ、入力件数、データ分布も考慮すると考えられます。

これらの注意点を踏まえると、小さなリストでは読みやすさを優先し、重複を許さず検索回数が多い場合はHashSetを検討する流れになります。Setを使う場合は順序が不要か、重複が落ちても問題ないかを確認してから置き換えるのが実用的です。

カスタマイズ方法

カスタマイズが必要になるのは、containsメソッドの戻り値だけでは情報が足りない場面です。存在確認だけでなく位置を取りたい、独自条件で判定したい、複数の属性をまとめて調べたい場合は、補助メソッドやラムダ式を使います。

ただし、標準APIで足りる処理まで独自実装に置き換えると、保守の負担が増えますし、これが一つの目安です。完全解説としては、標準の使い方を軸にしつつ、必要な部分だけカスタマイズする方針が扱いやすいです。

独自のcontainsメソッドの作成

具体的には、検索語が含まれるかだけでなく開始位置も返したい場合、intを返す補助メソッドを作れます。標準のindexOfでも近い処理はできますが、学習用には探索の流れを明示したサンプルコードが理解に役立ちます。

public class CustomContains {
    public static int customContains(String haystack, String needle) {
        for (int i = 0; i <= haystack.length() - needle.length(); i++) {
            if (haystack.substring(i, i + needle.length()).equals(needle)) {
                return i;
            }
        }
        return -1;
    }
    public static void main(String[] args) {
        String str = "Javaプログラミング";
        String search = "プロ";
        int position = customContains(str, search);
        System.out.println(position);
    }
}

結果: 期待される出力は4です。"Javaプログラミング"では"プロ"がインデックス4から始まるため、その位置が返ります。

このカスタマイズでは、見つからない場合に-1を返しています。JavaのString.indexOfと似た約束にしておくと、ほかの開発者が戻り値の意味を推測しやすくなると言えるでしょう。独自メソッドでは、haystackneedlenullのときに例外にするのか、-1を返すのかも決めておく必要があると整理できます。

ℹ️ 補足: 実用コードで位置だけが必要なら、標準のindexOfを先に検討します。独自のcontainsメソッドは、特殊な比較条件や学習目的がある場合に限定すると管理しやすくなるのが基本です。

ラムダ式を使用した柔軟な検索条件の適用

そのカスタマイズをコレクションへ広げるなら、Predicateを受け取るメソッドが使えます。Java 8以降のラムダ式を使うと、検索条件を呼び出し側から渡せるため、年齢、名前、数値範囲などの条件を一つの形で扱えます。

import java.util.ArrayList;
import java.util.function.Predicate;

public class LambdaContains {
    public static <T> boolean lambdaContains(ArrayList<T> list, Predicate<T> predicate) {
        for (T item : list) {
            if (predicate.test(item)) {
                return true;
            }
        }
        return false;
    }
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        boolean result = lambdaContains(list, (Integer x) -> x > 2);
        System.out.println(result);
    }
}

結果: 期待される出力はtrueです。listには34が含まれ、ラムダ式x -> x > 2を満たす値が存在します。

この使い方はStream.anyMatchに近い発想です。独自メソッドにする理由が薄い場合は標準のstream().anyMatch(predicate)を選び、独自の前処理やログ出力が必要な場合だけラッパー化すると保守しやすくなります。

使い分けると、標準APIで済む検索は短く書き、業務ルールを含む検索だけをカスタマイズできるのが目安です。Javaのうるう年判定のような条件分岐の練習と合わせると、Predicateに渡す判定式も組み立てやすくなります。

その設計では、メソッド名も戻り値に合わせると読みやすくなります。lambdaContainsbooleanを返すなら存在確認に限定し、抽出した要素を返す場合はfilterByfindByのような名前に分けると、使い方の誤解を避けられますが、覚えておくと役立つでしょう。

まとめ

Javaのcontainsメソッドは、文字列では部分文字列、コレクションでは要素の存在をbooleanで返す検索処理です。完全解説として見ると、単体の使い方だけでなく、ListSetMapStreamの役割を分けることが理解の近道になります。

そのため、初心者はString.containsで文字列検索を確認し、次にList.containsで要素検索へ進むと整理しやすくなります。大文字小文字、null、データ構造の違いは注意点として早めに押さえると、プログラミング中の予期しないfalseや例外を減らせますし、ここを基本と考えるとよいでしょう。

一方、標準のcontainsメソッドで足りない場合は、indexOfmatchesanyMatchPredicateを組み合わせます。カスタマイズは目的を絞るほど読みやすくなり、サンプルコードのように戻り値の意味を明確にすると保守しやすくなります。

これらを踏まえると、Javaで検索処理を書くときは「何を含むか」「完全一致か部分一致か」「例外を避ける前処理があるか」を先に決めるのが実用的です。containsメソッドの使い方を軸にすれば、条件分岐からフィルタリングまで一貫した考え方で組み立てられますし、ここがポイントです。

Javaプログラミングでは、短い判定式ほど読みやすく見える反面、大小文字、空白、null、データ構造の性質が結果を左右します。完全解説のサンプルコードを基準に、検索対象と戻り値の意味を確認しながら書けば、初心者でもcontainsメソッドを実用的な部品として扱えます。

関連記事

著者: Japanシーモア編集部

Japanシーモアは、Web/IoT/APP/SYS 分野のプログラミング情報を体系的に提供するメディアです。本記事は編集部による執筆とAI支援を組み合わせて制作し、公開前に編集部が校正しています。誤りや改善案がございましたらお問い合わせよりご連絡ください。

※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。