10. Strings and String Processing

10.5. From the Java Library: java.lang.StringBuffer

 

java.sun.com/j2se/1.5.0/docs/api/


ONE PROBLEM with the keywordSearch() method 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.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

resultStr=resultStr+ptr+" "

 

 

 

Before assignment

 

resultStr (Orphan object)

After assignment

 

 

 

Figure 7.9: Evaluating resultStr

= resultStr + ptr + " " creates an orphan object that must be garbage collected.


 

 

 

JAVA LANGUAGE RULE

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 keyword- Search() ends up with the correct value? he answer is that every time we assign a new value to resultStr, Java has to create a new String object. Figure 7.9 illustrates the process. Thus, given the statement

,,

J

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 + " " (Fig. 7.9a). It would then assign the new ob- ject as the new referent of resultStr (Fig. 7.9b). 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 or-

 

SECTION 7.5 From the Java Library: java.lang.StringBuffer309

phaned object. However, this algorithm does consume more of Java’s resources than other algorithms we might use.

 

 

A more efficient way to write the keywordSearch() method would make use of a StringBuffer to store and construct the resultStr. Like the String class, the java.lang.StringBuffer class also rep- resents a string of characters. However, unlike the String class, a StringBuffer can be modified, and it can grow and shrink in length as necessary. As Figure 7.10 shows, the StringBuffer class contains several of the same kind of methods as the String class, for exam- ple, charAt() and length(). But it also contains methods that allow characters and other types of data to be inserted into a string, such as append(), insert(), and setCharAt(). Most string-processing algo- rithms use StringBuffers instead of Strings as their preferred data structure.


 

 

 

 

 

 

 

 

 

 

 

Choosing the appropriate data structure

 

 

 

The 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 String.

The typical way to use a StringBuffer is shown in the following revised version of the keywordSearch() method:

,,

 

 

 

 

 

 

 

J

We declare resultStr as a StringBuffer instead of a String. Then,

instead of concatenating the ptr and reassigning the resultStr, we

append() the ptr to the resultStr for each occurrence of a keyword.

 

Similarly, after the loop exits, we insert() the count at the front (index


Figure7.10:The java.lang.StringBuffer class.

 

 

 

 

 

 

 

Strings are immutable


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 insert() and append() methods. These make it pos- sible to insert any type of data—int, double, Object, and so on—into a StringBuffer. The method itself takes care of converting the data into a string for us.

To summarize, String objects in Java are immutable. So when a String is “modified,” this really means that a new String object is cre- ated and the old String object must be garbage collected. This is some- what inefficient, especially if done repeatedly within a loop. To avoid these inefficiencies, use a StringBuffer instead of a String in such contexts.