簡體   English   中英

使用append時,StringBuilder使用更多內存

[英]StringBuilder uses more memory when append is used

{
    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)替換fileBuff.append("\\r\\n").append(currLine)我的內存幾乎fileBuff.append("\\r\\n").append(currLine)了一倍~ 33264440
有人可以解釋原因,因為我知道String連接也使用StringBuilder

我: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長。

使用StringBuilder您需要預留空間來向緩沖區添加字符串。 這是使用StringBuilder而不是string的一個很好的例子,因為你正在使用while循環。

當你使用String ,每次輸入如下內容:

String s = s + someOtherString;

你丟棄現有的s字符串並創建一個新字符串而不是s + someOtherString 這意味着你經常需要新的內存來制作連接的字符串,拋出舊的字符串,並將變量的引用放到新的字符串中。

使用StringBuilder您可以附加到字符串,而無需刪除現有部分。

所以是的,它使用了更多的內存,但與僅使用字符串相比,它在某些情況下非常有效。

換句話說: String是一個不可變對象,StringBuilder則不是。


在你的代碼中:

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

這與new String("\\r\\n" + currLine); 這是1個String對象

你正在使用1追加。

在你的評論中你說如果你使用這個:

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

這與new String("\\r\\n"); new String(currLine); 這是2個String對象

你幾乎翻了一倍的記憶。 這是有道理的,因為你正在進行2次附加,因此使用了兩倍的內存。

我想寫這篇關於@JRENs答案的評論,但我沒有足夠的代表。 2個追加的原因需要更多內存,請訪問http://docs.oracle.com/javase/tutorial/java/data/buffers.html

String中不可用的StringBuilder上的主要操作是append()和insert()方法,它們被重載以接受任何類型的數據。 每個都將其參數轉換為字符串,然后將該字符串的字符追加或插入字符串生成器中的字符序列。

因此,每個追加操作都會創建一個新的String,這就是為什么2個追加(每個循環)占用的內存大約是一個追加的兩倍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM