おーたにさんに何か書けと言われたので何か書いてみます。
よくjavaで「+」つかって文字列結合すると遅いから止めた方がいいよって言われますよね?どんなケースでもまずいんでしょうか?気になったので調べてみました。
こんな感じでいくつか文字列を結合するサンプルを作ってそれをjavapにかけてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class A { public String a(String s) { s = s + "a"; s = s + "b"; return s; } public String b(String s) { s += "a"; s += "b"; return s; } public String c(String s) { return s + "a" + "b"; } public String d(String s) { return "a" + "b"; } } |
javapにかけるとこんな感じの出力になります。全部だすとみづらいので、適当に整形したり抜き出したりしてます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
javap -classpath . -c A | egrep -e 'public|invokevirtual|ldc|new' | sed -e 's|java/lang/||g' public class A extends java.lang.Object{ public A(); public java.lang.String a(java.lang.String); 0: new #2; //class StringBuilder 8: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 11: ldc #5; //String a 13: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 16: invokevirtual #6; //Method StringBuilder.toString:()LString; 20: new #2; //class StringBuilder 28: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 31: ldc #7; //String b 33: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 36: invokevirtual #6; //Method StringBuilder.toString:()LString; public java.lang.String b(java.lang.String); 0: new #2; //class StringBuilder 8: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 11: ldc #5; //String a 13: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 16: invokevirtual #6; //Method StringBuilder.toString:()LString; 20: new #2; //class StringBuilder 28: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 31: ldc #7; //String b 33: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 36: invokevirtual #6; //Method StringBuilder.toString:()LString; public java.lang.String c(java.lang.String); 0: new #2; //class StringBuilder 8: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 11: ldc #5; //String a 13: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 16: ldc #7; //String b 18: invokevirtual #4; //Method StringBuilder.append:(LString;)LStringBuilder; 21: invokevirtual #6; //Method StringBuilder.toString:()LString; public java.lang.String d(java.lang.String); 0: ldc #8; //String ab |
a, bの場合はよくいわれているように結合のたびにStringBuilderが作られてます。
cの場合のように全部「+」でつなげるだけだと、StringBuilderは一回だけしか作られないです。
dの場合のようにリテラルだけの場合は「+」でつないでも StringBuilder は作られず、そのままリテラルとして埋め込まれているようです。
どんな場合でも新しいStringBuilderが作られるわけじゃないらしいです。
というわけで、「パフォーマンスチューニングだぜ!」とかいってなんでもかんでもStringBuilderにすればいいってわけじゃないんだよってお話でした。
おしまい。
最近のコメント