Section 7.5 From the Java Library: java.lang.StringBuffer
One problem with the
keywordSearch() method (Listing 7.4.2) is that it is not very efficient because a
String in Java is a read-only object. This means that once it has been instantiated, a
String cannot be changed. You cannot insert new characters or delete existing characters from it.
Principle 7.5.1. Strings Are Immutable.
Once instantiated, a Java
String cannot be altered in any way.
Given this fact, how is it possible that the
resultStr in the
keywordSearch() ends up with the correct value? The answer is that every time we assign a new value to
resultStr, Java has to create a new
String object. Figure 7.5.2 illustrates the process. Thus, given the statement
resultStr = resultStr + ptr + " ";
Java will evaluate the right-hand side, which creates a new
String object whose value would be the concatenation of the right-hand-side elements,
resultStr + ptr + " " (Part (a) of Figure 7.5.2). It would then assign the new object as the new referent of
resultStr (Part (b) of Figure 7.5.2). This turns the previous referent of
resultStr into an orphan object —that is, into an object that no longer has any references to it.
Java will eventually dispose of these orphaned objects, removing them from memory in a process known as garbage collection. However, creating and disposing of objects is a task that consumes the computer's time.
The fact that this assignment statement occurs within a loop means that several new objects are created and later garbage collected. Because object creation is a relatively time-consuming and memory-consuming operation, this algorithm is somewhat wasteful of Java's resources.
Of course, except for the inefficiency of doing it this way, no real harm is done by this algorithm used in the
keywordSearch() method. Java's garbage collector will automatically reclaim the memory used by the orphaned object. However, this algorithm does consume more of Java's resources than other algorithms we might use.
Principle 7.5.3. Automatic Garbage Collection.
An object that has no reference to it can no longer be used in a program. Therefore, Java will automatically get rid of it. This is known as garbage collection.
A more efficient way to write the
keywordSearch() method would make use of a
StringBuffer (Figure 7.5.4) to store and construct the
resultStr. Like the
String class, the
java.lang.StringBuffer class also represents a string of characters. However, unlike the
String class, a
StringBuffer can be modified, and it can grow and shrink in length as necessary.
StringBuffer class contains several of the same kind of methods as the
String class, for example,
length(). But it also contains methods that allow characters and other types of data to be inserted into a string, such as
setCharAt(). Most string-processing algorithms use a
StringBuffer instead of
String as their preferred data structure.
Principle 7.5.5. PROGRAMMING TIP: StringBuffer.
StringBuffer should be used instead of a
String for any task that involves modifying a string.
StringBuffer class provides several methods that are useful for string processing. The constructor method,
StringBuffer(String), makes it easy to convert a
String into a
StringBuffer. Similarly, once you are done processing the buffer, the
toString() method makes it easy to convert a
StringBuffer back into a
The typical way to use a
StringBuffer is shown in the following revised version of the
resultStr as a
StringBuffer instead of a
String. Then, instead of concatenating the
ptr and reassigning the
ptr to the
resultStr for each occurrence of a keyword. Similarly, after the loop exits, we
count at the front (index 0) of the
resultStr. Finally, we convert
resultStr into a
String by using the
toString() method before returning the method's result.
One advantage of the
StringBuffer class is that there are several versions of its
append() methods. These make it possible to insert any type of data —
Object, and so on —into a
StringBuffer. The method itself takes care of converting the data into a string for us.
String objects in Java are immutable. So when a
String is “modified,” this really means that a new
String object is created and the old
String object must be garbage collected. This is somewhat inefficient, especially if done repeatedly within a loop. To avoid these inefficiencies, use a
StringBuffer instead of a
String in such contexts.
Exercises Self-Study Exercise
1. Revised Keyword Search.
Run the code below to test the revised
keywordSearch() method. Add additional calls to