Principle 7.5.1. Strings Are Immutable.
Once instantiated, a Java
String cannot be altered in any way.
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.
String cannot be altered in any way.
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 + " ";
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.

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

java.lang.StringBuffer class.StringBuffer class contains several of the same kind of methods as the String class, for example, 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 algorithms use a StringBuffer instead of String as their preferred data structure.
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.
StringBuffer is shown in the following revised version of the keywordSearch() method:
keywordSearch() mrthod.public String keywordSearch(String s, String keyword)
{
// Create StringBuffer
StringBuffer resultStr = new StringBuffer();
int count = 0;
int ptr = s.indexOf(keyword);
while (ptr != -1) {
++count;
resultStr.append(ptr + " "); // Append to buffer
ptr = s.indexOf(keyword, ptr + 1);
}
resultStr.insert(0, count + ": ");
return resultStr.toString(); // Convert buffer to String
} // keywordSearch()
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 0) of the resultStr. Finally, we convert resultStr into a String by using the toString() method before returning the method’s result.
StringBuffer class is that there are several versions of its insert() and append() methods. These make it possible 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.
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.
keywordSearch() method. Add additional calls to keywordSearch().