Javaの String とか StringBuilder のメソッドについてまとめてみた

# 0. 始めに
　Java8 Silver取得に向けて絶賛勉強中の自分が、StringやStringBuilderのメソッドについてまとめた記事です。
ここではJava Silver受験する上で押さえておきたい、String や StringBuilder のメソッドを紹介しています。お察しの通り未熟者ですので、間違いがありましたら、ご指摘いただけると幸いです。

　次章から、Stringのメソッド・StringBuilder のメソッドの順に説明していきます。

# 1. Stringについて
Stringそのものについては、ざっくりとだけ説明します。押さえるポイントは
> ・プリミティブ型ではなく、参照型である
> ・Immutableである(一度定義されたら、メモリ上では書き変わらない)

ってところでしょうか。Stringはchar[]で文字列を扱っています。そのため下記の方法では、参照値は別のものでも、参照先のオブジェクトは同じになります(コードは、[参考2][ref1]より引用)。

```java
String a = "りんご";
String b = new String("りんご");
String c = new String(new char[]{'り', 'ん', 'ご'});
System.out.println(a); // りんご
System.out.println(b); // りんご
System.out.println(c); // りんご
```

また、Immutableとは言いましたが、再代入出来ない訳ではないです。再代入すると、変数の参照先が切り替わります(詳しくは、[参考3][ref2]の記事をご覧ください)。

# 2. String の主なメソッド
それでは本題、以下、「ここ、テストに出るよ！」なメソッドたちです(メソッドの一覧は、参考1より引用)。
(メソッドの紹介がダラダラと続くので、実際に手を動かしてコードを書いてみて下さい)

## char charAt(int i)
　`i`で指定した位置にある文字を返します。元の文字列は変化しません。
(コードの見方： // の後ろに書かれた文字が、出力される文字列を表しています)

```java
String str = "Hello Java!";

System.out.println(str.charAt(4));  // o
System.out.println(str);  // Hello Java!
```

## String concat(String str)
　strで指定した文字列を、後ろに連結します。やっぱり元の文字列は変わりません。

```java
String str = "Hello ";

System.out.println(str.concat("Java!"));  // Hello Java!
System.out.println(str);  // Hello 
```

## boolean equalsIgnoreCase(String str)
　対象の文字列と`str`を、大文字小文字を区別せず、比較します。

```java
String str = "Hello Java!";

System.out.println(str.equalsIgnoreCase("HELLO JAVA!"));  // true

// equals で比較した場合
System.out.println(str.equals("HELLO JAVA!")); // false
```


## int indexOf(int ch), int lastIndexOf(int ch)
　この2つはセットでおぼえましょう！
どちらも、`ch`で指定した文字が最初に登場した位置を返します。

　`indexOf` は、文字列を左から、`lastIndexOf` は右から探します。そして、一番左の文字を0番目として該当の文字が何番目にあるか教えてくれます(空白も1文字として数えます)。

```java
String str = "Hello Java!";
// H  e  l  l  o     J  a  v  a   !
// 0  1  2  3  4  5  6  7  8  9  10

System.out.println(str.indexOf("l"));  // 2
System.out.println(str.lastIndexOf("l"));  // 3
```

## int length()
　文字列の文字数を返します。ここでも空白は1文字としてカウントします。

```java
String str = "Hello Java!";

System.out.println(str.length());  // 11
```

## String replace(char o, char n)
　文字列中にある文字`o`を、すべて文字`n`で置換した文字列を返します。

```java
String str = "Hello Java!";

System.out.println(str.replace('a', 'o'));  // Hello Jovo!
```

## boolean startsWith(String prefix), boolean endsWith(String suffix)
　こちらもセットで覚えて良さそうですね！

`startsWith`は、文字列が`prefix`から始まっていればtrueを返します。
`endsWith` は、文字列が`suffix`で終わっていればtrueを返します。

```java
String str = "Hello Java!";

System.out.println(str.startsWith("Hello"));  // true
System.out.println(str.startsWith("Hey!"));   // false

System.out.println(str.endsWith("Java!"));   // true
System.out.println(str.endsWith("python!")); // false
```

## String substring(int start, int end)
　`start`から、`end`番目の直前までの文字列、間にある文字列を返します。この「間にある」ってのが分かりにくいので、コードを見た方が理解が早いかもです。

　ポイントとしては、文字そのものではなく、文字の間を数えあげることです(下記の例では、パイプ( | )で元の文字列を区切って番号を付けています)。

```java
String str = "Hello Java!";

// | H | e | l | l | o |   | J | a | v | a  | ! |
// 0   1   2   3   4   5   6   7   8   9   10   11

// 第1引数、第2引数共に指定した場合
System.out.println(str.substring(2, 7));  // llo J

// 第1引数のみ指定した場合
// 以下の2つは同じ文字列を出力する
System.out.println(str.substring(2));  // llo Java!
System.out.println(str.substring(2, str.length()));  // llo Java!
```

## String toLowerCase(), String toUpperCase()
toLowerCase()は、大文字を小文字に変換します。元々小文字だった文字は、変化しません。

toUpperCase()は、小文字を大文字に変換します。それだけです。

```java
String str = "Hello Java!";

System.out.println(str.toLowerCase());  // hello java!
System.out.println(str.toUpperCase());  // HELLO JAVA!
```

## String trim()
　両端の半角空白を除去します。
ちょっと分かりにくいですが、文字数を数えてあげると一目瞭然ですね！

```java 
String str = " Hello Java! ";

System.out.println(str.trim());           // Hello Java!
System.out.println(str.trim().length());  // 11

System.out.println(str);           //  Hello Java! 
System.out.println(str.length());  // 13
```





# 3. StringBuilderについて
　StirngがImmutableな一方で、StringBuilderは再代入の際に参照先の値を置き換えます。
　要するに、Stringのメソッドが元々の文字列を変化させないのに対して、StringBuilderのメソッドは元々の文字列をを変えてしまうってことです。

### コンストラクタ
 StringBuilderの宣言の方法は、下記のやり方があります[^20]。

```java
// 1. フツーに宣言、初期容量は16文字
StringBuilder sb1 = new StringBuilder();

// 2. 初期容量 capacity 文字で宣言
// 80.0 など実数を入れるとコンパイルエラーになります、指定できる数字はintのみ
StringBuilder sb2 = new StringBuilder(int capacity);

// 3. strで初期化する
StringBuilder sb3 = new StringBuilder(String str);

// 4. 宣言して即座に出力
System.out.println(new StringBuilder("Hello Java!"));
```


# 4. StringBuilderの主なメソッド

## StringBuilder append(String str)
　strを文字列の後ろに付け加えます。Stringとは違い、元々の文字列は変化します。

```java
StringBuilder sb = new StringBuilder("Hello Java!");

System.out.println(sb.append(" World!!"));  // Hello Java! World!!
System.out.println(sb);  // Hello Java! World!!
```

## StringBuilder append(String str, int start, int end)
　範囲指定をして、文字列の一部だけを付け加える事もできます。
↓では、末尾の`!`を削っています。~~なんて芸のない例~~

```java
StringBuilder sb = new StringBuilder("Hello Java!");

System.out.println(sb.append(" World!!", 0, 6));  // Hello Java! World
System.out.println(sb);  // Hello Java! World
```

## StringBuilder insert(int offset, String str)
　このメソッドも文字を付け加えるためのものですが、付け加える位置まで指定できます。
分かり易さのため、パイプ( | )で元の文字列を区切って番号を付けます。

```java
StringBuilder sb = new StringBuilder("Hello Java!");
// | H | e | l | l | o |   | J | a | v | a  | ! |
// 0   1   2   3   4   5   6   7   8   9   10   11

System.out.println(sb.insert(10, "Script"));  // Hello JavaScript!
System.out.println(sb);  // Hello JavaScript!
```

## StringBuilder delete(int start, int end)
　`start`番目から、`end`番目の直前までの文字を削除します。

```java
StringBuilder sb = new StringBuilder("Hello Java");

System.out.println(sb.delete(2, 4));  // Heo Java!
System.out.println(sb);  // Heo Java!

// length() と合わせて使えば、全部の文字を削除できます
System.out.println(sb.delete(0, sb.length()));  // (何も出力されない)
```


## StringBuilder reverse()
　文字列の並びを逆にします。

```java
StringBuilder sb = new StringBuilder("Hello Java!");

System.out.println(sb.reverse());  // !avaJ olleH
System.out.println(sb);  // !avaJ olleH
```

## void setCharAt(int index, char ch)
　`index`番目の位置の**文字**を`ch`で置き換えます。

```java
StringBuilder sb = new StringBuilder("Hello Java!");

sb.setCharAt(6, 'j');
System.out.println(sb);  // Hello java!
```

## StringBuilder replace(int start, int end, String str)
　`start`番目から、`end`番目の直前までの文字を、`str`で置き換えます。置き換える文字数と`str`の文字数が一致していなくも大丈夫です。
setCharAtと違い、**文字列**の置き換えを行い、StringBuilder を返します。

```java
StringBuilder sb = new StringBuilder("Hello Java!");

System.out.println(sb.replace(6, 10, "python"));  // Hello python!
System.out.println(sb);  // Hello python!
```

## String substring()
　[Stringの`substring()`](#string-substringint-start-int-end)と全く同じ使い方が出来ます。


## String toString()
　ご覧の通り[^40]、StringBuilderをStringに変換してくれます。
String と比較するときなどに使います[^42]。

```java
StringBuilder sb = new StringBuilder("Hello Java!");
String str = "Hello Java!";

// str と sb の値が同じか比較
System.out.println( str.equals(sb.toString()) );  // true
```

## CharSequence subSequence(int start, int end)
　こちら実は、[Stringの`substring()`](#string-substringint-start-int-end)と全く同じ振る舞いをします(なので、元の文字列を変化させません)。
違いがあるとすれば、戻り値が`CharSeqence`なるオブジェクトになっていることでしょうか。
それから、元のオブジェクトは不変です。

```java
StringBuilder sb = new StringBuilder("Hello Java!");

  System.out.println(sb.subSequence(2, 8));  // oll Ja

  if (sb.subSequence(2, 8) instanceof CharSequence ) {
    System.out.println("this is CharSequence Object");  // 実行される
  }
}
```


# 5. 最後に
　Java Silverでは、String・StringBuilder のメソッドに関する問題が多く出題されます。所謂、基本的な事らしいですが、とは言え調べてまとめるのは大変です(でした)。
　この記事が少しでもString・StringBuilder の理解、試験の合格に役立てればと思います。

# 6. 参考
１．山本道子 (2015) Java プログラマ Silver SE 7(第5刷発行) ㈱翔泳社 発行
２．[図で理解するJavaの参照][ref1]
３．[【Java初心者】値渡しと参照の値渡し(”参照渡し”という言葉は誤解を生むとのことで修正しています)][ref2]


[ref1]: https://qiita.com/hysdsk/items/2e94c8722dc8f950e77c
[ref2]: https://qiita.com/chihiro/items/d3d9a028cd5dd8e84649
[ref3]: https://qiita.com/atsuk0r0/items/9336346c258bae2ee6e4

[^20]: 個人的には、4の方法はエラーになると思っていただけに驚きでした。
[^40]: どこがご覧の通りなんだろう、って後になって思いましたが、敢えて修正しないことにしました。
[^42]: 正しくはObjectクラスのメソッドですが、試験で良く出るので紹介まで。。。