As
we know java.lang.String is an immutable class. When we want to combine
Strings, a lot of new Strings will be created before we get the last result. In
some case as reading long text files or retrieving and concatenating big text
fields from DB, we should consider to use StringBuilder instead of String. We
will see how we could improve performance.
String – an immutable class
Immutable
classes offer safe threads when we use them. However, there is a disadvantage
of this type of classes is the number of existing objects. Every time we invoke
methods to change states of immutable objects, we truly create new objects. Let
we see an example:
String
message = "Java";
message
+= " is a programming";
message
+= "language.";
And
we will have message = “Java is a programming language.”. The question is: How
many String objects do we have after running this code? Three? Or four? The
answer is five Strings: 3 obviously Strings “Java”, “ is a programming”, and “ language”; the result String “Java is a programming language.”; and another one is “Java is a
programming”.
The “+” operation or the concat() method of String does copy contents of
original Strings to make a new String.
When
the frequency to combine Strings is large, we will get abysmal performance.
StringBuilder
is a mutable sequence of characters. StringBuilder is not synchronized as
StringBuffer. The main operations of StringBuilder are convert() and append().
We should use StringBuilder when we need to concatenate Strings.
Compare performance by using String and StringBuilder
My
computer uses Window 7 with Core i3 2.27GHz CPU and 4Gb Ram. I downloaded from
the Internet one text file having 10800 lines. We will see the simple code to
read this text file:
public class Test {
public static void
main(String[] args) {
long start
= System.currentTimeMillis();
readFile("sample.txt");
long stop =
System.currentTimeMillis();
System.out.println("Running
time: " + (stop - start) + " ms");
}
public static String
readFile(String filename) {
String
content = "";
try {
File file = new
File(filename);
FileReader
fr;
fr
= new FileReader(file);
BufferedReader
br = new BufferedReader(fr);
String
line = "";
while ((line
= br.readLine()) != null) {
content
+= line;
}
br.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return
content;
}
}
When
I run this code on my laptop, the output was “Running time: 16967 ms”, near by
17 seconds. Now let we change a bit to use StringBuilder:
public class Test {
public static void
main(String[] args) {
long start
= System.currentTimeMillis();
readFile("sample.txt");
long stop =
System.currentTimeMillis();
System.out.println("Running
time: " + (stop - start) + " ms");
}
public static String
readFile(String filename) {
StringBuilder
content = new StringBuilder();
try {
File
file = new File(filename);
FileReader
fr;
fr
= new FileReader(file);
BufferedReader
br = new BufferedReader(fr);
String
line = "";
while ((line
= br.readLine()) != null) {
content.append(line);
}
br.close();
}
catch (FileNotFoundException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO
Auto-generated catch block
e.printStackTrace();
}
return
content.toString();
}
}
Running
this code, I got the output: “Running time: 24 ms”, faster than 700 times! Therefore,
we easy decide what we should use on cases like this.