Cri*_*tiL 5 java string stringbuilder string-concatenation
{
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();
}
Run Code Online (Sandbox Code Playgroud)
在运行代码几次的时候,我得到了usedTotal ~ 14279888,但如果我用我替换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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
显然#II应该使用更少的内存,但事实并非如此.我正在阅读的文件是50k长.
使用时,StringBuilder您需要预留空间来为缓冲区添加字符串.这是一个使用StringBuilder而不是字符串的好例子,因为你正在使用while循环.
当你使用a时String,每次输入如下内容:
String s = s + someOtherString;
Run Code Online (Sandbox Code Playgroud)
你丢弃现有的s字符串并创建一个新字符串而不是它s + someOtherString.这意味着你经常需要新的内存来制作连接的字符串,抛出旧的字符串,并将变量的引用放到新的字符串中.
使用a,StringBuilder您可以附加到字符串而无需删除现有部分.
所以是的,它使用了更多的内存,但与仅使用字符串相比,它在某些情况下非常有效.
换句话说:String是一个不可变对象,StringBuilder而不是.
在你的代码中:
fileBuff.append("\r\n" + currLine);
Run Code Online (Sandbox Code Playgroud)
这与new String("\r\n" + currLine);1个String对象相同
你正在使用1追加.
在你的评论中你说如果你使用这个:
fileBuff.append("\r\n").append(currLine);
Run Code Online (Sandbox Code Playgroud)
这new String("\r\n");和new String(currLine);2个String对象相同
你几乎翻了一倍的记忆.这是有道理的,因为你正在进行2次附加,因此使用了两倍的内存.