こんにちは!エンジニアの中沢です。
Javaには文字列を検索するためのindexOfメソッドがあります。
この記事では、
・indexOfメソッドとは
・Listの中に特定の値(文字列)が含まれているか知りたい
・Listの中に特定の値(文字列)が含まれていたらその要素番号を知りたい
という基本的な内容から、
・indexOfメソッドで複数の要素を検索する方法
・StringとStringBufferの部分文字列を検索する方法が知りたい
・lastIndexOfメソッドとindexOfメソッドの違いが何かを知りたい
・containsとindexOfのパフォーマンス(速度)の比較を知りたい
などの応用的な使い方に関しても解説していきます。
今回はこれらの方法を覚えるために、indexOfメソッドのさまざまな使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
indexOfメソッドとは
文字列に含まれる部分文字列を検索するにはindexOfメソッドを使用します。
indexOfメソッドは、Listなどのコレクションや、String、StringBufferなどに対して使用します。
indexOfメソッドは次のように記述します。
public int indexOf(String str [,int index])
これを実際に使うときのようにわかりやすく記述すると次のようになります。
文字列やList.indexOf(検索したい文字列, 検索を開始するインデックス番号(省略可能))
indesOfメソッドは指定した部分文字列が見つかった場合は、文字列の先頭を”0”としたインデックス番号で返し、部分文字列が見つからなかった場合は”-1”を返します。
第2引数で検索開始位置を指定することができます。
indexOfメソッドは先頭から検索して最初に見つかった位置のインデックス番号を返すので、先頭以外の位置を検索したい場合に第2引数を指定します。
先頭から検索する場合には、第2引数を省略することができます。
indexOfメソッドの使い方
Listの中に特定の値が含まれているか調べるには、containsメソッドかindexOfメソッドのどちらかを使います。
containsメソッドはListの中に指定した要素がある場合に”true”を返します。
indexOfメソッドは指定した要素をListの先頭から検索して最初に見つかった位置のインデックスを返します。
そのため、
・List内に特定の要素があるかどうかを確認する場合はcontainsメソッド
・要素番号を知りたい場合はindexOfメソッド
と覚えましょう!
containsメソッドについてはこちらの記事で詳しく解説しているので、ぜひ確認してみてください。
ListでindexOf
ここでは、indexOfメソッドを使ってList内に特定の要素があるかどうかを確認する方法を解説します。
containsメソッドで値が存在するかどうかを調べる方法も同時に解説しているので、次のプログラムを見てみましょう。
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List list = new ArrayList<>(Arrays.asList("s", "a", "m", "u", "r", "a", "i")); boolean exists = list.contains("a"); int index = list.indexOf("a"); System.out.println("存在するか? = " + exists); System.out.println("要素番号 = " + index); } }
[実行結果]
存在するか? = true 要素番号 = 1
このようにcontainsメソッドとindexOfメソッドを使うことで、List内の要素の確認ができました!
StringでindexOf
前述したようにindexOfメソッドは、対象の文字列から指定した部分文字列を検索します。
部分文字列が見つかった場合は、文字列の先頭を0としたインデックス番号を返します。
以下にString型の文字列を検索する方法を記述します。
public class Main { public static void main(String[] args) { String str1 = "appleorangemelon"; String str2 = "orange"; int result = str1.indexOf(str2); if (result != -1) { System.out.println(str2 + "が見つかった位置:" + result); } else { System.out.println(str2 + "は見つかりませんでした"); } } }
[実行結果]
orangeが見つかった位置:5
StringBufferでindexOf
StringBufferクラスで指定した文字列でもStringと同様にindexOfメソッドを使用して、部分文字列を検索することができます。
以下にStringBufferクラスで指定した部分文字列を検索する方法を記述します。
public class Main { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append("appleorangemelon"); String str = "orange"; int result = sb.indexOf(str); if (result != -1) { System.out.println(str + "が見つかった位置:" + result); } else { System.out.println(str + "は見つかりませんでした"); } } }
[実行結果]
orangeが見つかった位置:5
StringBufferクラスの文字列も、indexOfメソッドで部分文字列が検索できることがわかりますね!
lastIndexOfメソッドの使い方
ここではlastIndexOfメソッドの使い方を解説します。
indexOfメソッドはListの先頭から検索して最初に見つかった位置のインデックスを返しますが、lastIndexOfメソッドは文字列の後ろから検索して最初に見つかった位置のインデックスを返します。
そのため、同じ要素が複数入っている場合には使うメソッドによって違う値が返ってきます!
ListでlastIndexOf
List内に特定の要素があるかどうかを確認する方法を、lastindexOfメソッドを使用したプログラムを見てみましょう。
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List list = new ArrayList<>(Arrays.asList("s", "a", "m", "u", "r", "a", "i")); int index = list.indexOf("a"); int lastIndex = list.lastIndexOf("a"); System.out.println("最初の要素番号 = " + index); System.out.println("最後の要素番号 = " + lastIndex); } }
[実行結果]
最初の要素番号 = 1 最後の要素番号 = 5
このように、Listに同じ要素が複数入っている場合にはindexOfメソッドとlastIndexOfメソッドで違う結果になることが確認できました!
StringでlastIndexOf
String型の文字列にlastindexOfメソッドを使用して、部分文字列を検索する方法を見ていきましょう。
以下にString型の文字列を検索する方法を記述します。
public class Main { public static void main(String[] args) { String str1 = "appleorangemelonorange"; String str2 = "orange"; int result = str1.lastIndexOf(str2); if (result != -1) { System.out.println(str2 + "が見つかった位置:" + result); } else { System.out.println(str2 + "は見つかりませんでした"); } } }
[実行結果]
orangeが見つかった位置:16
指定した部分文字列であるorangeは文字列に2つ含まれていますが、lastIndexOfメソッドでは、文字列の末尾から検索しますので、後方の2番目のorangeの位置を返します。
StringBufferでlastindexOf
StringBufferクラスで指定した文字列でもStringと同様にlastIndexOfメソッドを使用して、部分文字列を検索することができます。
以下にStringBufferクラスで指定した部分文字列を検索する方法を記述します。
public class Main { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append("appleorangemelonorange"); String str = "orange"; int result = sb.lastIndexOf(str); if (result != -1) { System.out.println(str + "が見つかった位置:" + result); } else { System.out.println(str + "は見つかりませんでした"); } } }
[実行結果]
orangeが見つかった位置:16
indexOfメソッドで複数の要素を検索する方法
ここでは、indexOfメソッドの第2引数を指定して複数の要素を検索する方法を解説します。
次のプログラムで確認してみましょう。
public class Main { public static void main(String[] args) { String str = "samurai"; int result; for (int i = 0; i < str.length(); i++) { result = str.indexOf("a", i); if (result != -1) { System.out.println("要素番号 = " + result); i = result; } } } }
[実行結果]
要素番号 = 1 要素番号 = 5
このプログラムでは、indexOfメソッドで指定した文字が含まれているかを検索しています。
文字が見つかった場合には、その位置の次のインデックスをindexOfメソッドの第2引数に指定することで、続きから残りの文字列を検索しています。
このようにしてindexOfメソッドの第2引数を指定して複数の要素を検索することができました!
自作クラス内の値をindexOfで検索する方法
indexOfメソッドを使って自作クラス内に特定の値が含まれているか確認するには、メソッドの内部でequalsメソッドを使用して、List内に特定の値があるかを判定します。
そのため、equalsメソッドをオーバーライドして自作クラス内の値と比較するように変更すると、indexOfメソッドで自作クラス内の値と比較することができるようになります。
次のプログラムで確認してみましょう。
import java.util.ArrayList; import java.util.List; class TestClass { String str; TestClass(String s){ str = s; } public boolean equals(Object obj) { TestClass tc = (TestClass)obj; String tcStr = tc.str; return str.equals(tcStr); } } public class Main { public static void main(String[] args) { List<TestClass> list = new ArrayList<>(); TestClass testClass = new TestClass("samurai"); list.add(testClass); TestClass testClass2 = new TestClass("samurai"); System.out.println("要素番号 = " + list.indexOf(testClass2)); } }
[実行結果]
要素番号 = 0
ここではequalsメソッドをオーバーライドして自作クラス内に定義したプロパティをチェックしています。
containsとindexOfのパフォーマンス(速度)の比較
containsメソッドとindexOfメソッドは使い方が似ているため、どちらを使ってもいい場合はパフォーマンス(速度)が良い方を使いたいですよね。
ここでは、containsメソッドとindexOfメソッドのパフォーマンス(速度)の比較を行います。
次のプログラムで確認してみましょう。
public class Main { public static void main(String[] args) { String[] str = new String[100]; for (int i = 0; i < 100; i++) { str[i] = "appleorangemelon"; } // contains検索処理開始 long start1 = System.nanoTime(); for (int j = 0; j < 100; j++) { boolean b = str[j].contains("orange"); } // contains処理終了時間 long end1 = System.nanoTime(); System.out.println("contains:" + (end1 - start1) / 1000000f + "ms"); // indexOf検索処理開始 long start2 = System.nanoTime(); for (int k = 0; k < 100; k++) { int num = str[k].indexOf("orange"); } // indexOf処理終了時間 long end2 = System.nanoTime(); System.out.println("indexOf:" + (end2 - start2) / 1000000f + "ms"); } }
[実行結果]
contains:0.089792ms indexOf:0.08806ms
このプログラムでは、containsメソッドとindexOfメソッドでそれぞれ100回検索した場合の処理速度を比較しています。
実行結果から、ほとんど速度に違いがないことがわかりました。
そのため、どちらを使っても問題はありません。
まとめ
いかがでしたか?
今回はListやString、StringBufferの中に特定の文字列や値が含まれているかどうかを調べる方法について解説しました。
indexOfメソッドはList内に同じ要素が複数あっても、最初の要素番号しか返さないことに注意してください。
同様に、lastIndexOfメソッドは最後の要素番号しか返さないので気をつけてくださいね。
もしindexOfメソッドやlastIndexOfメソッドの使い方を忘れてしまったらこの記事を確認してください!