5
{
    StringBuilder fileBuff = new StringBuilder();
    long before = getUsedMem();
    try {
    //Open InputStreamReader here
        while ((currLine = lnr.readLine()) != null) {
            fileBuff.append("\r\n" + currLine);
        }
     //Close streams
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("usedTotal: " + (getUsedMem() - before));
}

private long getUsedMem() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

コードを数回実行すると、usedTotal ~ 14279888が得られますが、に置き換えるとfileBuff.append("\r\n").append(currLine)、ほぼ 2 倍のメモリ ~ 33264440が得られます。連結も使用する
ことを知っているので、誰かが理由を説明してもらえますか?StringStringBuilder

I: fileBuff.append("\r\n" + currLine);

      62: aload         6
  64: invokevirtual #16                 // Method java/io/LineNumberReader.readLine:()Ljava/lang/String;
  67: dup           
  68: astore_2      
  69: ifnull        99
  72: aload_1       
  73: new           #2                  // class java/lang/StringBuilder
  76: dup           
  77: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
  80: ldc           #17                 // String \r\n
  82: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  85: aload_2       
  86: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  89: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  92: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  95: pop           
  96: goto          62

II fileBuff.append("\r\n").append(currLine)

      62: aload         6
  64: invokevirtual #16                 // Method java/io/LineNumberReader.readLine:()Ljava/lang/String;
  67: dup           
  68: astore_2      
  69: ifnull        86
  72: aload_1       
  73: ldc           #17                 // String \r\n
  75: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  78: aload_2       
  79: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  82: pop           
  83: goto          62

明らかに #II は少ないメモリを使用するはずですが、そうではありません。私が読んでいるファイルの長さは50kです。

4

2 に答える 2

6

を使用StringBuilderすると、バッファに文字列を追加するためのスペースが確保されます。StringBuilderこれは、 while ループを使用しているため、文字列ではなく使用する良い例です。

を使用しているときはString、次のように入力するたびに:

String s = s + someOtherString;

既存の文字列を捨てて、s代わりに新しい文字列を作成していますs + someOtherString。これは、連結された文字列を作成し、古いものを破棄し、変数の参照を新しい文字列に配置するために、常に新しいメモリが必要であることを意味します。

を使用するStringBuilderと、既存の部分を削除せずに文字列に追加できます。

はい、より多くのメモリを使用しますが、文字列だけを使用する場合と比較して、シナリオによっては非常に効率的です。

つまりString、 は不変オブジェクトであり、 aStringBuilderはそうではありません。


あなたのコードで:

fileBuff.append("\r\n" + currLine);

new String("\r\n" + currLine);これは、どれが 1 つの String オブジェクトであるかと同じです。

1 つの追加を使用しています。

あなたのコメントでは、これを使用する場合:

fileBuff.append("\r\n").append(currLine);

これは、 2 つの String オブジェクトであるnew String("\r\n");and と同じです。new String(currLine);

ほぼ 2 倍のメモリが得られます。2倍の追加を行っているため、2倍のメモリを使用しているため、これは理にかなっています。

于 2013-07-05T11:11:00.787 に答える