それが僕には楽しかったんです。

僕と MySQL と時々 MariaDB

java【文字列】

プログラミングにおいて、文字列を操作出来るようになるとかなり出来ることの幅が広がると言われるほど文字列を扱うことは重要である

 

そのことを踏まえて、javaで文字列を扱うとはどういうことかまとめてみる

 

まず第一に、扱う文字列をどう定義するか。

 

1.Stringクラスを使う

javaでは文字列を扱うにはまずStringクラスを使う

クラスというぐらいなのでnewを用いた方法で定義可能である

String str = new String("hello,world");
System.out.println(str);//print -> hello,world

上記のコードではstrという参照型変数にStringオブジェクトが代入され
その動作によりStringオブジェクトの生成が完了します。

更に、Stringクラスには文字列を操作するための様々なメソッドが用意されており、特に良く使う物をあげます

メソッド 機能
length 文字列の長さを返す
equals 引数の文字列と同じ内容の文字列か調べる
charAt 指定したインデックスの文字列を文字として切り出す
indexOf 引数の文字を検索する
split 文字列を引数の文字列で区切って配列にする
contains 引数の文字を含むか検索
substring 部分文字列を取得
compareTo どちらが辞書的に大きいか比較

ここで示したメソッドだけでも大抵のことが出来ますが
逆に、Stringクラスに定義されているメソッド以外のことは出来ません
もしStringクラスに含まれていない機能を扱いたいのなら独自のクラスを定義する必要があります
しかし、実際はStringクラスに含まれるメソッドでほぼすべて実現できるのでそれ以外の機能が必要な場合はそれらを見なおして必要性を考えてください

そして設計上Stringクラスは読み込み専用のクラスなので、Stringオブジェクトそのものを変更することは出来ません
もし変更したい場合は「StringBuilderクラス」を使用します

2.文字列操作の使用例

StringBuilderクラスを説明する前に、さっき示した文字列の具体例

public class Test{
	public static void main(String... args){
		String str = new String("<hello,world>");//これは推奨されない
		
		int start = str.indexOf("<");
		//indexOfは存在するときはそのインデックスを返す
		//存在しないなら−1を返す
		if(0 <= start){
			start++;//substring使用時に最初の<が含まれてしまうので+1
			int end = str.indexOf(">");
			if(0 <= end){
				//部分文字列の切り出し
				System.out.println(str.substring(start,end));
			}
		}
	}
}

3.文字列リテラル

実は今まで紹介してきた文字列の定義方法には問題があります

String str = new String("hello,world");

という定義方法では"hello,world"を生成する為に一度Stringオブジェクトが生成され
それをもう一度参照型変数strにStringオブジェクトを生成して代入しているからです。
つまり一度の生成のつもりが2回生成していることになります
これはとても非効率なので、もっと簡単に一度で済ませてしまう方法があります

String str = "hello,world";

このように生成したい文字列をダブルクォーテーションで囲むことで文字列リテラルとして扱われ
Stringオブジェクトの生成は一回だけです


4.StringBuilderクラス

1.Stringクラスにも書いた様にStringクラスは読み込み専用でオブジェクトそのものを変更できません
正確には、オブジェクトを変更できるメソッドは存在しますが、変更のたびにオブジェクトを生成するのでとても非効率です
そこで効率良く文字列を変更可能なクラスがStringBuilderクラスです

String -> StringBuidlerの変換

String str = "hello";
StringBuilder sb = new StringBuilder(str);

これで指定した文字列をStringBuilderに定義できます
またStringBuilderクラスのオブジェクトを生成するときには引数を指定しなくても大丈夫です
更にはオブジェクトそのものを変更出来るのでStringクラスを何回も生成する必要が無いためループ内で文字列を操作する場合はとても効率的です

StringBuilderクラスにはStringクラス同様いろんなメソッドが存在しますがよく使うものをあげます

メソッド 機能
append 指定した文字列を末尾に追加
indexOf Stringクラス同様
insert 指定した文字列を指定位置に挿入
replace 指定した文字列を置換する
substring Stringクラス同様
toString Stringオブジェクトに変換する


そしてStringクラスとStringBuilderクラスはCharSequenceという共通のインターフェースを実装しているので以下のメソッドはどちらのクラスでも共通します

メソッド 機能
charAt 指定インデックスの文字の取得
length 文字列の長さ取得
subSequence 部分文字列の取得

5.文字列の比較

文字列を比較することで主に初心者の多いミスですが「==」や「!=」と言った演算子で比較してしまうこと
特に==を用いた比較です

String str1 = "hello";
String str2 = new StringBuilder("hello").toString();
str1 == str2//これは真にはならない

str1 == str2が真にならないのには大きな理由があります
それは==演算子では同一オブジェクトへの参照であるかを判定しているため
異なる文字列オブジェクトのstr1,str2では必ず偽になります
また異なる文字列オブジェクトを比較するなら通常equalsを用いて行われます
その場合内容自体はおなじなので真が返ってくるというわけです

なので一般的に文字列オブジェクトの比較では、equalsメソッドを使用し比較します

しかし、ここまでの方法は文字列オブジェクト、あくまでもStringオブジェクト同士の比較だけです
実はStringBuilderクラス同士の比較ではequalsを使っても偽になるため
StringBuilder同士ではtoStringで変換してからcontentEqualsを使う

これで大体の文字列の扱いに関する基礎的なことは大丈夫だと思う