もくじとまとめ
お勉強用の自分向けメモです
- そもそものStringとStringBuilderの違いについて
- StringBuilderのequalsについて
結論は
- 結合や反転をガンガン行うときはStringBuilderを推奨
- そうでないときはStringの方が便利 & 安全かも
- StringやStringBuilderで文字列の一致判定は気を付けよう!
背景
最近AtCoder問題を利用してJavaの文法とかを勉強しています。
ABC146 F -Sugoroku
に出くわした際にStringを反転させたいなーと思ったところStringBuilderなるものに出会ったことから始まるお話です。
StringとStringBuilderの違い
これについては以下のリンクを見ればわかりやすいと思います。
https://qiita.com/shunsuke227ono/items/e8f34c67dcffa0fa28ad
https://www.javadrive.jp/start/stringbuilder/
簡単にまとめると、
- Stringはイミュータブルであり、StringBuilderはミュータブルである
- コード上ではStringもミュータブルのように記述できる(S = S + "a"など)
- 文字列の追加・挿入ではStringBuilderの方がメモリ・時間効率が良い
ということでStringBuilderの使用が推奨されている感じなのですが、String側の利点に全く出会わなかったので、あれ?Stringいらない子なのかな?ってなりました(おそらくそんなことはない)。
―――2020/02/02追記―――
(併せてタイトルを変更しました)
コメントにてご指摘および↓良いリンク↓の紹介をしていただきました。
https://qiita.com/yoshi389111/items/67354ba33f9271ef2c68
文字列定数の結合の場合や、1ステートメントでの結合の場合は+演算子で問題ないようです。
今回のように文字列反転をしたい場合は、StringBuilderやList<Character>を使用した方が良いようです。
追記2(2020/03/27)
違う問題と知見に出会ったので追記
ABC159 B - String Palindrome
文字列が回文であるか(+α)の判定。
あるStringBuilderとそれを反転させたものが同一かどうかという発想でコードを書きました。
static boolean checkKaibun(String str){
StringBuilder t = new StringBuilder(str);
return (t.equals(t.reverse()));
}
自分で試した限りではこれは常にtrueを返します。
原因はStringBuilderのequalsメソッドがオーバーライドされていないことです。
解決策は
1. equalsメソッドをオーバーライドする
2. toStringでStringに変換してから比較する
コード中にStringBuilderの比較をたくさん使うなら1でしょうが、hashCodeメソッドのオーバーライドも行う必要もあるらしく(下記の参考)、面倒です。
参考
https://www.atmarkit.co.jp/ait/articles/0702/20/news103.html
2での実装は以下のようになります。
static boolean checkKaibun(String str){
StringBuilder t = new StringBuilder(str);
return (str.equals(t.reverse().toString()));
}