繁体   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