web-dev-qa-db-ja.com

Javaで文字列を連結すると、メモリ内にいくつの文字列が作成されますか?

Javaの不変文字列について尋ねられました。いくつかの "a"を文字列に連結する関数を作成する必要がありました。

私が書いたもの:

public String foo(int n) {
    String s = "";
    for (int i = 0; i < n; i++) {
        s = s + "a"
    }
    return s;
}

次に、ガベージコレクションが発生しないと仮定して、このプログラムが生成する文字列の数を尋ねられました。 n = 3に対する私の考えは

  1. 「」
  2. 「あ」
  3. 「あ」
  4. 「ああ」
  5. 「あ」
  6. 「aaa」
  7. 「あ」

基本的に、ループの各反復で2つの文字列が作成されます。しかし、答えはn2。この関数によってメモリ内に作成される文字列は何ですか?なぜそうなのですか?

17
ahalbert

次に、ガベージコレクションが発生しないと仮定して、このプログラムが生成する文字列の数を尋ねられました。 n = 3に対する私の考えは(7)でした

文字列1(_""_)と2(_"a"_)はプログラム内の定数です。これらは物事の一部として作成されるのではなく、コンパイラーが知っている定数であるため「内部化」されます。これについて詳しくは、Wikipediaの String interning を参照してください。

また、文字列5および7は、文字列#2と同じ_"a"_であるため、カウントから削除されます。これにより、文字列#3、#4、および#6が残ります。答えは、コードを使用して「n = 3に対して3つの文字列が作成される」です。

Nの数2 n = 3の場合、これは明らかに間違っています。これは9であり、最悪の場合の回答でさえ7しかありません。インターンされていない文字列が正しかった場合、回答は2n + 1です。

それで、これをどのようにすべきかの質問ですか?

String is immutable なので、変更可能なもの、つまり新しいオブジェクトを作成せずに変更できるものが必要です。 StringBuilder です。

最初に確認するのはコンストラクタです。この場合、文字列の長さがわかり、コンストラクターStringBuilder(int capacity)があります。つまり、必要なだけ正確に割り当てることができます。

次に、_"a"_はStringである必要はありませんが、文字_'a'_にすることができます。これは、append(String)append(char)を呼び出すと、パフォーマンスが少し向上します。append(String)を使用すると、メソッドは、文字列の長さを調べて、いくつかの作業を行う必要があります。それ。一方、charは常に正確に1文字です。

コードの違いは StringBuilder.append(String) vs StringBuilder.append(char) で確認できます。それはtooに関係するものではありませんが、雇用主に印象づけようとしている場合は、可能な限り最善の方法を使用するのが最善です。

まとめると、これはどのように見えますか?

_public String foo(int n) {
    StringBuilder sb = new StringBuilder(n);
    for (int i = 0; i < n; i++) {
        sb.append('a');
    }
    return sb.toString();
}
_

1つのStringBuilderと1つのStringが作成されました。追加の文字列をインターンする必要はありません。


Eclipseで他の簡単なプログラムをいくつか作成します。 pmd をインストールし、作成したコードで実行します。それが不平を言うことに注意し、それらのことを修正してください。ループ内で+を含む文字列の変更を検出し、それをStringBuilderに変更した場合、maybeが初期容量を検出し、しかし、.append("a").append('a')の違いを確実にキャッチします

26
user40980

各反復で、新しいString+演算子によって作成され、sに割り当てられます。返却後、最後を除くすべてがガベージコレクションされます。

"""a"などの文字列定数は、毎回作成されるわけではありません。これらは 内部文字列 です。文字列は不変なので、自由に共有できます。これは文字列定数に起こります。

文字列を効率的に連結するには、 StringBuilder を使用します。

9
9000

MichaelTが彼の回答で説明しているように、コードはO(n)文字列を割り当てます。ただし、O(n2)バイトのメモリとO(n2)時間。

O(n2)バイト。割り当てている文字列の長さは0、1、2、…、n-1、nであり、合計すると(n2 + n)/ 2 = O(n2)。

時間もO(n2)、i番目の文字列を割り当てるには、長さがi-1の(i-1)番目の文字列をコピーする必要があるため。これは、割り当てられた各バイトをコピーする必要があることを意味し、O(n2)時間。

多分これは面接官が意味したものですか?

4
svick