Javaを利用したプログラミングにおいて、文字列の中に特定の文字やキーワードが含まれているかを確認する処理は、非常に頻繁に登場します。
ユーザーからの入力内容のチェック、ログファイルからの特定キーワードの抽出、あるいはデータのフィルタリングなど、その用途は多岐にわたります。
Javaには、このような「文字列の包含判定」を行うための方法が複数用意されており、目的に応じて最適なメソッドを選択することが、コードの可読性やパフォーマンスを向上させる鍵となります。
本記事では、Javaで文字列を含むか判定する代表的な手法であるcontains、indexOf、そして正規表現を用いたmatchesなどの使い方を詳しく解説します。
それぞれの特徴や使い分けのポイントを理解し、実務で役立つスキルを身につけていきましょう。
Javaで文字列の包含判定を行う主要なメソッド
Javaのjava.lang.Stringクラスには、文字列の中に特定の文字列が含まれているかを調べるためのメソッドがいくつか定義されています。
最も一般的で直感的なものはcontainsメソッドですが、判定だけでなく「どこにあるか」という位置情報が必要な場合にはindexOfメソッドが利用されます。
また、より複雑なパターン(例えば、数字が含まれているか、特定の形式に従っているかなど)を判定したい場合には、正規表現を利用する方法が適しています。
まずは、最も基本となるcontainsメソッドから詳しく見ていきましょう。
String.containsメソッドによる判定
containsメソッドは、Java 5から導入されたメソッドであり、対象の文字列に指定した文字列が含まれているかどうかをboolean型(true/false)で返します。
引数にはCharSequenceインターフェースを指定するため、StringだけでなくStringBuilderなども渡すことが可能です。
このメソッドの最大の特徴は、「含まれているかどうか」という意図がコード上で非常に明確になる点です。
戻り値が直接的な判定結果であるため、if文などの条件分岐でそのまま利用するのに適しています。
public class ContainsExample {
public static void main(String[] args) {
String message = "Javaプログラミングを楽しもう";
String searchWord = "Java";
// 文字列が含まれているか判定
if (message.contains(searchWord)) {
System.out.println("指定した単語 '" + searchWord + "' が見つかりました。");
} else {
System.out.println("指定した単語は見つかりませんでした。");
}
// 大文字・小文字は区別される
boolean isPresent = message.contains("java");
System.out.println("小文字の 'java' は含まれるか: " + isPresent);
}
}
指定した単語 'Java' が見つかりました。
小文字の 'java' は含まれるか: false
上記のコードからわかるように、containsメソッドは大文字と小文字を厳密に区別します。
そのため、”Java”と”java”は異なるものとして扱われる点に注意が必要です。
String.indexOfメソッドによる判定
indexOfメソッドは、指定した文字列が最初に出現する位置を0から始まるインデックス(整数値)で返します。
もし指定した文字列が見つからない場合は、-1を返します。
Java 5以前では、文字列の包含判定を行うためにこのindexOfが頻繁に使われていました。
現在でも、「含まれているかどうか」だけでなく、「どこに含まれているか」という位置情報が必要な場合には、このメソッドが必須となります。
public class IndexOfExample {
public static void main(String[] args) {
String text = "Javaはオブジェクト指向言語です。Javaは人気があります。";
String target = "Java";
// 文字列が含まれているか位置で判定
int index = text.indexOf(target);
if (index != -1) {
System.out.println("'" + target + "' はインデックス " + index + " に最初に出現します。");
} else {
System.out.println("見つかりませんでした。");
}
// 2番目以降の出現を探す場合
int secondIndex = text.indexOf(target, index + 1);
System.out.println("2番目の '" + target + "' はインデックス " + secondIndex + " です。");
}
}
'Java' はインデックス 0 に最初に出現します。
2番目の 'Java' はインデックス 17 です。
indexOfは第二引数に検索開始位置を指定できるため、特定の場所より後を探したいといった柔軟な処理が可能です。
単純な真偽値が必要なだけならcontainsを、位置を知りたい、あるいは古いソースコードとの互換性を保ちたい場合はindexOfを使うと良いでしょう。
正規表現を用いたString.matchesとPatternクラス
より高度な検索条件、例えば「特定の文字列で始まるか」「数字3桁が含まれているか」といったパターンを判定したい場合には、正規表現(Regular Expression)を使用します。
String.matchesメソッドは、文字列全体がパターンに一致するかどうかを判定します。
ここで注意が必要なのは、一部が含まれているかどうかを調べたい場合、パターンの前後に.*(任意の文字列)を付ける必要がある点です。
public class RegexExample {
public static void main(String[] args) {
String text = "注文番号は:ABC-12345 です。";
// 「ABC-」で始まり、その後に数字が続くか判定
// .* を使うことで、その前後に何があっても良いことを示す
if (text.matches(".*ABC-\\d+.*")) {
System.out.println("指定されたパターンの文字列が含まれています。");
}
// String.matches は全体一致が必要なため、単に "ABC" では false になる
System.out.println("単なる 'ABC' での判定: " + text.matches("ABC"));
}
}
指定されたパターンの文字列が含まれています。
単なる 'ABC' での判定: false
頻繁に同じ正規表現を使う場合は、java.util.regex.PatternクラスとMatcherクラスを使用する方がパフォーマンス面で有利です。
また、Matcher.find()メソッドを使えば、matchesのように全体一致を気にせず「部分一致」を簡単に判定できます。
大文字・小文字を区別せずに判定する方法
現実のアプリケーション開発では、ユーザーが入力した文字列を検索する際、大文字と小文字の差異を無視したいケースが非常に多くあります。
しかし、前述の通りcontainsやindexOfはデフォルトでこれらを区別します。
大文字・小文字を無視して判定を行うための代表的な2つのアプローチを紹介します。
全てを小文字(または大文字)に変換して比較する
最もシンプルでよく使われる手法は、比較対象と検索ワードの両方を一度小文字に変換してから判定する方法です。
これにはtoLowerCase()メソッドを使用します。
public class CaseInsensitiveExample {
public static void main(String[] args) {
String original = "Welcome to Java World";
String keyword = "JAVA";
// 両方を小文字にしてから比較
if (original.toLowerCase().contains(keyword.toLowerCase())) {
System.out.println("大文字小文字を区別せずに '" + keyword + "' を検出しました。");
}
}
}
大文字小文字を区別せずに 'JAVA' を検出しました。
この方法は実装が簡単ですが、文字列が非常に長い場合や、ループ内で大量に実行する場合には、新しい文字列オブジェクトが都度生成されるため、メモリ消費やパフォーマンスに影響を及ぼす可能性があることに留意してください。
Patternクラスのフラグを利用する
正規表現のPatternクラスを使用すると、オブジェクトのコピーを作成せずに大文字・小文字を無視した判定が可能です。
Pattern.CASE_INSENSITIVEフラグを指定することで、スマートに解決できます。
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class PatternExample {
public static void main(String[] args) {
String text = "Learning Java is Fun";
String regex = "java";
// CASE_INSENSITIVE フラグを立ててコンパイル
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("正規表現フラグを使用して '" + regex + "' を検出しました。");
}
}
}
正規表現フラグを使用して 'java' を検出しました。
この方法は、特にパフォーマンスが求められるシーンや、複雑な条件と併用したい場合に非常に有効です。
空文字やnullのチェックと安全な判定
文字列操作を行う際に最も注意すべきは、NullPointerException (NPE) です。
対象の文字列がnullである場合、containsなどのメソッドを呼び出すとプログラムが異常終了してしまいます。
モダンなJava開発においては、判定を行う前に必ずnullチェックを行うか、ライブラリを活用して安全に処理を行うことが推奨されます。
public class SafetyCheckExample {
public static void main(String[] args) {
String input = null;
// 安全なチェックの書き方
if (input != null && input.contains("Java")) {
System.out.println("含まれています。");
} else {
System.out.println("nullまたは含まれていません。");
}
}
}
また、Java 11以降では文字列が空、あるいは空白文字のみであるかを判定するisBlank()メソッドなども追加されています。
包含判定を行う前段階のバリデーションとしてこれらを組み合わせることで、より堅牢なプログラムを作成できます。
各メソッドの比較と使い分けまとめ
ここまで紹介したメソッドの特性を表にまとめました。
状況に応じて最適なものを選択しましょう。
| メソッド名 | 戻り値の型 | 主な用途 | 特徴 |
|---|---|---|---|
contains | boolean | 単純な包含確認 | 最も直感的で読みやすい。Java 5以降の標準。 |
indexOf | int | 出現位置の特定 | 見つからない場合は -1 を返す。位置情報が必要な時に使用。 |
matches | boolean | パターンマッチング | 正規表現を使用。全体一致が必要な点に注意。 |
Pattern/Matcher | 任意 | 高度な検索・抽出 | 再利用性が高く、大文字・小文字無視などのオプションが豊富。 |
パフォーマンスに関する考察
単純な文字列の包含確認であれば、containsとindexOfのパフォーマンス差はほとんどありません。
なぜなら、内部実装においてcontainsはindexOfを呼び出しているからです。
一方で、正規表現(matches)は、単純な文字列比較に比べて処理コストが高くなります。
パターン解析のプロセスが発生するためです。
固定の文字列を含んでいるか確認するだけであれば、containsを使用するのがベストプラクティスです。
まとめ
Javaで文字列に特定のキーワードが含まれているか判定する方法には、用途に合わせた最適な選択肢が用意されています。
- 単純に「含まれているか」を知りたい場合
containsメソッドを使用する。- 「どこにあるか」という位置情報が必要な場合
indexOfメソッドを使用する。- 大文字・小文字を区別したくない場合
toLowerCase()で統一するか、Patternクラスのフラグを活用する。- 複雑なパターンを扱いたい場合
正規表現(
Pattern/Matcher)を利用する。
文字列操作は、あらゆるJavaアプリケーションの基礎となります。
各メソッドの挙動を正しく理解し、実行効率とコードの読みやすさを両立させた実装を心がけましょう。
特にnull安全なコードを書く習慣をつけることで、バグの少ない高品質なプログラムを構築できるようになります。






