{
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();
}
While running the code several times, I get usedTotal ~ 14279888, but if I replace with fileBuff.append("\r\n").append(currLine)
I get almost double the memory ~33264440.
Can somebody please explain the reason, as I know String
concatenation also uses StringBuilder
?
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
Clearly #II should use less memory, but it doesn't. The file I am reading is 50k long.
As for StringBuilder s, they are also mutable and memory efficient, they are the fastest in string manipulation, but unfortunately they are not thread-safe. If you take these facts into the consideration, you will always make the right choice!
StringBuilder. append(boolean a) is an inbuilt method in Java which is used to append the string representation of the boolean argument to a given sequence. Parameter: This method accepts a single parameter a of boolean type and refers to the Boolean value to be appended.
There are 13 various overloaded append() methods in both StringBuffer and StringBuilder classes.
It is O(1) when appending single characters. A StringBuilder is like an ArrayList. When you append a single item the cost is O(1). Appending a string is like calling addAll()--the cost is proportional to the length of the string / the number of items being added.
When using StringBuilder
you're reserving space to add strings to your buffer. This is a good example to use StringBuilder
rather than string because you're using a while loop.
When you're using a String
, every time you type something like this:
String s = s + someOtherString;
You're throwing away your existing s
string and creating a new one to go instead of it which is s + someOtherString
. This means that you're constantly needing new memory to make the concatenated string, throw the old one out, and put the reference of your variable to your new string.
With a StringBuilder
you can append to your string without having to remove the existing part.
So yes, it uses more memory, but it's very efficient in some scenario's compared to using just a string.
In other words: String
is an immutable object and a StringBuilder
isn't.
In your code:
fileBuff.append("\r\n" + currLine);
This is the same as new String("\r\n" + currLine);
which is 1 String object
You're using 1 append.
In your comment you say that if you use this:
fileBuff.append("\r\n").append(currLine);
This is the same as new String("\r\n");
and new String(currLine);
which are 2 String objects
You get almost double the memory. That makes sense because you're doing 2x append, thus using double the memory.
I wanted to write this as a comment on @JRENs answer but I don't have enough rep. The reason 2 appends take more memory is here http://docs.oracle.com/javase/tutorial/java/data/buffers.html
The principal operations on a StringBuilder that are not available in String are the append() and insert() methods, which are overloaded so as to accept data of any type. Each converts its argument to a string and then appends or inserts the characters of that string to the character sequence in the string builder.
So, each append operation creates a new String, which is why 2 appends (per loop) takes roughly twice as much memory as one append.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With