1. ホーム
  2. java

[解決済み] SQLでStringBuilderを使用する正しい方法

2023-04-22 03:41:09

質問

私はちょうど私のプロジェクトでこのようないくつかのSQLクエリのビルドを見つけました。

return (new StringBuilder("select id1, " + " id2 " + " from " + " table")).toString();

これは StringBuilder はその目的、すなわちメモリ使用量の削減を達成しているのでしょうか?

コンストラクタの中で'+'(Stringの連結演算子)を使っているので、そうとは思えません。以下のコードのようにStringを使用するのと同じ量のメモリを消費するのでしょうか? 私が理解したところでは、以下のように StringBuilder.append() .

return "select id1, " + " id2 " + " from " + " table";

両方のステートメントは、メモリ使用量が等しいかそうでないか?明確にしてください。

事前にありがとうございます。

編集してください。

ところで は私のコードではありません。 . 古いプロジェクトで見つけたものです。また、クエリは私の例のものほど小さくはありません。)

どのように解決するのですか?

<ブロッククオート

StringBuilderを使用する目的、すなわちメモリの削減。それは達成されていますか?

いいえ、全くできていません。そのコードでは StringBuilder を正しく使っていません。(引用を間違えていると思いますが、確かに id2table ?)

(通常) 目的はメモリを減らすことであることに注意してください。 チャーン を減らすことであり、ガベージコレクタを少し楽にすることです。

以下のようにStringを使用するのと同じようにメモリを消費するのでしょうか?

いいえ、それは より メモリチャーンを引き起こします。(JVMオプティマイザが、明示的な StringBuilder が不要であり、可能であれば、それを最適化するまで)。

もしそのコードの作者が StringBuilder を使いたいのであれば(賛成も反対もあります。この回答の最後の注意を参照してください)、適切に行う方が良いでしょう(ここでは、実際には id2table ):

StringBuilder sb = new StringBuilder(some_appropriate_size);
sb.append("select id1, ");
sb.append(id2);
sb.append(" from ");
sb.append(table);
return sb.toString();

なお、私がリストアップした some_appropriate_size の中に StringBuilder のコンストラクタで指定することで、 これから追加するすべての内容に対して十分な容量を確保できるようになります。指定しない場合に使用されるデフォルトのサイズは 16文字 で、これは通常小さすぎて、結果的に StringBuilder は自分自身を大きくするために再割り当てをしなければならなくなります (IRC、Sun/Oracle JDK では、自分自身を 2 倍にします [あるいは、もし特定の append を満たすためにさらに必要であるとわかっている場合は、それ以上)。

聞いたことがあるかもしれませんが、文字列連結の を使う StringBuilder を使います。これは本当で、それは一つの StringBuilder を使います。しかし、デフォルトのコンストラクタを使うので、ほとんどの場合、再割り当てを行う必要があります。しかし、読みやすくなります。なお、これは ではなく の真偽は不明です。 シリーズ を連結したものです。ですから、例えば、これは1つの StringBuilder :

return "prefix " + variable1 + " middle " + variable2 + " end";

と大まかに訳されます。

StringBuilder tmp = new StringBuilder(); // Using default 16 character size
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();

だからいいんです。デフォルトのコンストラクタとそれに続く再割り当て(s)は理想的ではありませんが、十分に良い確率です。そして、連結したものが ロット になり、より読みやすくなります。

しかし、これは1つの式の場合だけです。複数の StringBuilder が使われます。

String s;
s = "prefix ";
s += variable1;
s += " middle ";
s += variable2;
s += " end";
return s;

結局こんな感じになっちゃうんですよね。

String s;
StringBuilder tmp;
s = "prefix ";
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable1);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" middle ");
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable2);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" end");
s = tmp.toString();
return s;

...これはかなり醜いです。

しかし、非常に少数のケースを除いて、すべての 問題ではない であり、特定のパフォーマンスの問題がない限り、読みやすさ (これは保守性を向上させます) を優先させることを覚えておくことが重要です。