This topic illustrates the performance improvement techniques in String and StringBuffer with the following sections:
-
Overview of String and StringBuffer
-
Better way of creating Strings
-
Optimization by interning Strings
-
Optimization techniques when Concatenating Strings
-
Optimization by initializing StringBuffer
- Key Points
Overview of String and StringBuffer :
Immutable objects cannot be modified once they are created.
Mutable objects can be modified after their creation.
String objects are immutable where as StringBuffer objects are mutable.
You need to carefully choose between these two objects depending on the situation for better performance. The following topics illustrate in detail :
Note: This section assumes that reader has some basic knowledge of Java Strings and StringBuffer.
Better way of creating Strings :
You can create String objects in the following ways.
1. String s1 = "hello";
String s2 = "hello";
2. String s3 = new String("hello");
String s4 = new String("hello");
Which of the above gives better performance?
Here is a code snippet to measure the difference.
package com.demo;
public class StringTest {
public static void main(String[] args) {
// create String literals
long startTime = System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
String s1 = "hello";
String s2 = "hello";
}
long endTime = System.currentTimeMillis();
System.out.println("Time taken for creation of String literals : "
+ (endTime - startTime) + " milli seconds");
// create String objects using 'new' keyword
long startTime1 = System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
String s3 = new String("hello");
String s4 = new String("hello");
}
long endTime1 = System.currentTimeMillis();
System.out.println("Time taken for creation of String objects : "
+ (endTime1 - startTime1) + " milli seconds");
}
}
The output of this code
Time taken for creation of String
literals : 0 milli seconds
Time taken for creation of String objects : 170 milli
secondsIt clearly shows first type of creation is much more faster than second type of creation. Why?
Because the content is same s1 and s2 refer to the same object where as s3 and s4 do not refer to the same object. The 'new' key word creates new objects for s3 and s4 which is expensive.
How the JVM works with Strings:
Java Virtual Machine maintains an internal list of references for interned Strings ( pool of unique Strings) to avoid duplicate String objects in heap memory. Whenever the JVM loads String literal from class file and executes, it checks whether that String exists in the internal list or not. If it already exists in the list, then it does not create a new String and it uses reference to the existing String Object. JVM does this type of checking internally for String literal but not for String object which it creates through 'new' keyword. You can explicitly force JVM to do this type of checking for String objects which are created through 'new' keyword using String.intern() method. This forces JVM to check the internal list and use the existing String object if it is already present.
So the conclusion is, JVM maintains unique String objects for String literals internally. Programmers need not bother about String literals but they should bother about String objects that are created using 'new' keyword and they should use intern() method to avoid duplicate String objects in heap memory which in turn improves java performance. see the following section for more information.
The following figure shows the creation of String Objects without using the intern() method.
You can test the above difference programmatically using == operator and String.equals() method.
== operator returns true if the references point to the same object but it does not check the contents of the String object where as String.equals() method returns true if the contents of the String objects are equal.
s1==s2 for the above code returns true because s1 and s2 references point to the same object.
s3.equals(s4) for the above code returns true because both objects content is same which is "hello".
You can see this mechanism in the above figure. Here, we have three separate objects which contain same content,"hello". Actually we don't need separate objects because they use memory and take time to execute.
How do you make sure that the String objects are not duplicated?
The next topic covers this interesting interning String mechanism.
Optimization by Interning Stings
In situations where String objects are duplicated unnecessarily, String.intern() method avoids duplicating String objects. The following figure shows how the String.intern() method works. The String.intern() method checks the object existence and if the object exists already, it changes point of reference to the original object rather than create a new object.
The following figure shows the creation of String literal and String Object using intern
package com.demo;
public class StringInternTest {
public static void main(String[] args) {
// create String references like s1,s2,s3...so on..
String variables[] = new String[50000];
for (int i = 0; i < variables.length; i++) {
variables[i] = "s" + i;
}
// create String literals
long startTime0 = System.currentTimeMillis();
for (int i = 0; i < variables.length; i++) {
variables[i] = "hello";
}
long endTime0 = System.currentTimeMillis();
System.out.println("Time taken for creation of String literals : "
+ (endTime0 - startTime0) + " milli seconds");
// create String objects using 'new' keyword
long startTime1 = System.currentTimeMillis();
for (int i = 0; i < variables.length; i++) {
variables[i] = new String("hello");
}
long endTime1 = System.currentTimeMillis();
System.out.println("Time taken for creation of String objects with 'new' key word : "
+ (endTime1 - startTime1) + " milli seconds");
// intern String objects with intern() method
long startTime2 = System.currentTimeMillis();
for (int i = 0; i < variables.length; i++) {
variables[i] = new String("hello");
variables[i] = variables[i].intern();
}
long endTime2 = System.currentTimeMillis();
System.out.println("Time taken for creation of String objects with intern(): "
+ (endTime2 - startTime2) + " milli seconds");
}
}
Here is the output of the above code
Time taken for creation of String literals : 0 milli seconds
Time taken for creation of String objects with 'new' key word : 160 milli seconds
Time taken for creation of String objects with intern(): 60 milli seconds
No comments:
Post a Comment