【Java】文字列操作関連

2018年3月11日

本稿は、文字列操作関連で私が便利だと思った機能に絞り、それぞれ紹介します。

文字列操作は、ほとんどの分野で必須なので、ある程度操作できるようになっておきましょう。

もちろん、ここで紹介する以外にも便利なメソッドがたくさんあるので、是非Stringクラスのドキュメントを読んでみてください。

equalsメソッド

おなじみequalsメソッドでの文字列値比較です。

public class Test{
	public static void main(String[] args){
		String s = "猫";
		System.out.println("猫".equals(s));
		System.out.println("犬".equals(s));
	}
}
実行結果

true
false

余談・・・

「s.equals(“猫”)」と書いても基本的に同じことができますが、私は「”猫”.equals(s)」のほうをお勧めします。

理由はぬるぽ落ちしないからです。

Stringクラスのソースを見ればわかるのですが、s.equalsではsがnullの場合、ぬるぽがその時点で発生しますが、”猫”.equalsならsがnullだったとしても、equalsメソッド内部でnull instanceof Stringが実行され、次に処理を行わず、falseを返すようになっているんですね。

もちろんnullと固定値をtrueにしたい場合には使えませんが、大抵はfalseにしたいことが多いと思うので、nullチェックが不要な、固定値.equals(変数)の書き方を積極的に使うと無駄な工数をかけなくて済みますしソースも短くなります。

startsWithメソッド

文字列の先頭が指定した文字列で始まるかどうか、判定します。

public class Test{
	public static void main(String[] args){
		String s = "ABCD";
		System.out.println(s.startsWith("ABC"));
		System.out.println(s.startsWith("ABD"));
	}
}
実行結果

true
false

endsWithメソッド

文字列の先頭が指定した文字列で始まるかどうか、判定します。

public class Test{
	public static void main(String[] args){
		String s = "ABCD";
		System.out.println(s.endsWith("ABC"));
		System.out.println(s.endsWith("BCD"));
	}
}
実行結果

false
true

lengthメソッド

文字列の長さを取得できます。

public class Test{
	public static void main(String[] args){
		String s = "ABCあD";
		System.out.println(s.length());
		System.out.println("スーパー関西人".length());
	}
}
実行結果

5
7

toUpperCaseメソッド

アルファベットを大文字に変換できます。

public class Test{
	public static void main(String[] args){
		String s = "Abcあ真D";
		System.out.println(s.toUpperCase());
	}
}
実行結果

ABCあ真D

toLowerCaseメソッド

アルファベットを小文字に変換できます。

public class Test{
	public static void main(String[] args){
		String s = "Abcあ真D";
		System.out.println(s.toLowerCase());
	}
}
実行結果

abcあ真d

indexOfメソッド

先頭から文字列を検索し、最初に登場する文字列の番号を返します。
一致しなかった場合は-1を返します。

public class Test{
	public static void main(String[] args){
		String s = "sAbあかさAbX";
		System.out.println(s.indexOf("Ab"));
		
		//4番目の文字列から検索開始したい場合
		System.out.println(s.indexOf("Ab",3));
		
		//検索に引っかからない
		System.out.println(s.indexOf("AGb"));
	}
}
実行結果

1
6
-1

後述するsubstringメソッドと一緒に使用することで、特定の文字列を抜き出したりできます。

指定文字列を含むかどうかも判定できますし、汎用性の高いメソッドです。

まあ、指定文字列を含むかどうかの比較はcontainsメソッドでもできるんですけどね・・・

lastIndexOfメソッド

文字列終端から検索し、最初に登場する文字列の番号を返します。
一致しなかった場合は-1を取得します。

public class Test{
	public static void main(String[] args){
		String s = "sAbあかさAbX";
		System.out.println(s.lastIndexOf("Ab"));
		
		//4番目の文字列から先頭方向へ検索
		System.out.println(s.lastIndexOf("Ab",3));
		
		//検索に引っかからない
		System.out.println(s.lastIndexOf("AGb"));
	}
}
実行結果

6
1
-1

replaceメソッド

指定した文字列全てを別の文字列で置き換えます。

public class Test{
	public static void main(String[] args){
		String s = "sAbあかさAbX";
		System.out.println(s.replace("Ab","ウッひょー"));
	}
}
実行結果

sウッひょーあかさウッひょーX

substringメソッド

文字列の抜き出しができます。

public class Test{
	public static void main(String[] args){
		String s = "sAbあかさAbX";
		
		//文字列の7番目から最後まで抜き出し
		System.out.println(s.substring(6));
		
		//文字列の4番目から6番目までを抜き出し
		System.out.println(s.substring(3, 6));
	}
}
実行結果

AbX
あかさ

splitメソッド

文字列をString配列に分割できます。

public class Test{
	public static void main(String[] args){
		String s = "100,200,300";
		String[] spl = s.split(",");
		for ( String n : spl ) {
			System.out.println(n);
		}
	}
}
実行結果

100
200
300

気を付けなければならないのが、指定する文字列は正規表現だということです。

正規表現とは文字列を曖昧検索するための手段です。例えば「A+」を表す正規表現はAが一文字以上続くことを表します。

正規表現について興味がある方はこちらのサイト等で勉強してください。

「+」文字等の正規表現文字は通常の記述では正規表現として扱われてしまうので分割できません。

では、「A+」区切りで分割したい場合どうするのかというと、こうします。

public class Test{
	public static void main(String[] args){
		String s = "100A+200A+300";
		String[] spl = s.split("A\\+");
		for ( String n : spl ) {
			System.out.println(n);
		}
	}
}
実行結果

100
200
300

ここで、でてきた「\\」(円マークまたはバックスラッシュ)ですが、正規表現文字を通常の文字として読み込ませるための文字です。これを一般的には「エスケープする」とか言われたりします。

正規表現を普通の文字列として読み込ませたい場合は正規表現文字の直前に「\」文字を入れるのですが、Javaの文字列「””」内部にも「\」でエスケープできるようになっています。

よって、Javaの文字列内に「\」を入れたい場合は「\\」と記述する必要があるのですね。

joinメソッド

文字列配列を、指定した文字列区切りで結合した文字列に変換します。

public class Test{
	public static void main(String[] args){
		String[] s = {"100","200","300"};
		System.out.println(String.join(",", s));
	}
}
実行結果

100,200,300

カンマ区切りで、データを保存するようなセーブファイルを作成する時とかに使えるかもしれませんね。

StringBuilderクラス

Javaで文字列結合は「+」演算子が利用されますが、複数の文字列をたくさん結合していきたい場合は「+」演算子での結合はやめたほうがいいです。

理由は非効率だからです。

使い方はこんな感じです。

public class Test{
	public static void main(String[] args){
		StringBuilder sb = new StringBuilder();
		sb.append("犬");
		sb.append("猫");
		sb.append("サル");
		String s = sb.toString();
		System.out.println(s);
	}
}
実行結果

犬猫サル


学生時代に自作マップエディタを開発している時に書き出しファイルにCSV形式を採用していたのですが、マップが広くなると書き出し速度が異常に遅くなる現象に遭遇しました。

その時から、たくさんの文字列を結合する時は必ずStringBuilderを使用するようにしています。

無理して使用する必要はなく、文字列結合を少しするくらいなら、普通の+で構いません。

それでは最後に文字列結合による速度比較ができるサンプルを紹介します。

public class Test{
	public static void main(String[] args){
		//起動時のほうが処理が遅くなる為ダミー処理(効果あるかわからん)
		for ( int i = 0;i < 1000;i++ );
		final int testNum = 1000;
		
		long t = System.currentTimeMillis();
		StringBuilder test1 = new StringBuilder();
		for ( int i = 0;i < testNum;i++ ) test1.append("A");
		System.out.println(test1.substring(0,10));
		System.out.println("StringBuilder="+(System.currentTimeMillis()-t)+"ミリ秒\n");
		
		long t2 = System.currentTimeMillis();
		String test2 = "";
		for ( int i = 0;i < testNum;i++ ) test2+="A";
		System.out.println(test2.substring(0,10));
		System.out.println("+演算子="+(System.currentTimeMillis()-t2)+"ミリ秒");
	}
}
実行結果

AAAAAAAAAA
StringBuilder=1ミリ秒

AAAAAAAAAA
+演算子=16ミリ秒

表示文字列は結果が長すぎると見にくいと思ったので、あえてsubstringメソッドで先頭10文字のみ表示させました。

気にしないでください。

Aの文字列を1000回結合してみましたが、やはりStringBuilderが高速ですね。

当然文字列が多くなると速度差がかなり出てきますので、たった15ミリ秒程度の差だと思わないほうがいいです。

興味のある方はtestNumを修正して結合回数を増やして試してみてください。

・・・ちなみに、200000回結合すると私の環境では3000ミリ秒以上の差が出ています。

Java

Posted by nompor