Lesson 17

Learning Objectives
By the end of today's class, you should know...
  • Strings and the String pool
  • What is the difference between a StringBuffer, StringBuilder and String?
  • When would you choose to declare a String, StringBuilder and StringBuffer variable?
  • What are some of the common StringBuilder methods?


The String Class

  • In CIS 36A, you learned about a class called String that allows the storage of multiple characters as a single piece of data
  • The String class provides many useful methods for working with Strings, including:
    • length(): Returns the length of this string. The length is equal to the number of Unicode code units in the string.
    • charAt(index): Returns the char value at the specified index. An index ranges from 0 to length() - 1. The first char value of the sequence is at index 0, the next at index 1, and so on, as for array indexing.
    • substring(beginIndex, endIndex): Returns a string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1.
    • indexOf(ch): Returns the index within this string of the first occurrence of the specified character. If a character with value ch occurs in the character sequence represented by this String object, then the index (in Unicode code units) of the first such occurrence is returned.
    • replace(oldChar, newChar): Returns a string resulting from replacing all occurrences of oldChar in this string with newChar.
  • As well as overloaded versions of some of the above methods
  • Many of these methods are made possible by the fact that the String class uses a private final char array to store its value:
public final class String {
    private final char value[];
}
  • Therefore, the String class offers the benefits of an array, including its indexing system.

String Immutability

  • The String class is what is known as an immutable class.
    • Once an object of this class has been created, it can never be changed.
  • Immutability is achieved by storing the data in a private and final variable (as shown above)
  • Additionally, none of the String methods alter the contents of this array.
  • Instead, a method like replace, which seemingly alters the String, will return a new String instead of altering the original one.
Why Make String Immutable?
  • String variables are used in a wide variety of applications where security is important, such as database connections, network connections, opening files
  • Were String not immutable, a connection or file name could be changed, leading to a potential security threat.
The String Pool
  • One unique aspect of String's immutability is its use of the "String pool"
  • The String pool is a "pool" of all String constants stored in the heap memory.
  • Each time a new String variable is declared and assigned a value, Java searches the String pool to determine if that value already exists in the String pool.
    • If the value does not yet exist in the String pool, it will be added.
    • If it does exist, the new String variable will store a reference to the location of that existing String.
  • For example:
String pool in the heap


  • In the above example, s1 and s3 are both storing references to the same location in memory (where "Apple" is located)
  • Therefore, we can use == to compare them for equality (true!), as they are both storing a reference to the same object.
  • However, if we want to create a new object, separate from the "Apple" value already stored in the String pool, we can call an alternate String constructor:
String s4 = new String("Apple"); //added to the heap, but not the String pool
  • In this case, s1 != s4
  • Using the new keyword always results in the creating of a new String object.
  • A new String object gets created using the assignment operator (=) or "", only when a matching String object with the same value is not found in the String pool
  • The benefit of the String pool is that it allows the JVM to reuse String objects, and thus increase space efficiency (less memory is used) of programs.

String Pool Example:


class Test {
    public static void main(String[] args){
       
        String one = "hello";
        String two = "hello";
        String three = new String("hello");
        String four = "Hello";
        System.out.println("one == two: " + (one == two));
        System.out.println("one == three: " + (one == three));
        System.out.println("one.equals(three): " + (one.equals(three)));
        System.out.println("one == four: " + (one == four));
        System.out.println("three == \"hello\": " + (three == "hello"));
      
    }
}

Group Activity

  • How many String objects are created in the following program?
class Test {
    public static void main(String[] args){
       
        String a = "Apple";
        String b = "Papaya";
        String c = "Apple";
        String d = "papaya";
        String e = new String("Papaya");
        if (e == "Papaya") {
            System.out.println("Papaya");
        } else {
            System.out.println("Apple");
        }
      
    }
}


The StringBuffer and StringBuilder Classes

  • The StringBuffer and StringBuilder classes are similar to the String class, except that the StringBuffer and StringBuilder classes are mutable, whereas the value of a String object is fixed once it has been created.
StringBuilder is mutable
  • StringBuffer and StringBuilder objects can be used anywhere that a String object is used.
  • However, these two classes are more flexible than String, and, in certain cases, are a more efficient choice.

  • For example, when performing many concatenations (such as inside of a loop), it can be more efficient to use a StringBuffer or StringBuilder object, because these objects will simply update the values of their char arrays, rather than creating a brand new object.
  • Internally, the + operator for the String class has been optimized to use a StringBuilder:
String s1 = "hello";
String s2 = "world";
String concat = s1 + " " + s2;

//will be implicitly converted to the following

StringBuilder s = new StringBuilder();
concat = s.append(s1).append(s2).toString();

  • However, it will return a new StringBuilder object for each statement
    • Therefore, in a situation like a loop, there can be a heavy performance penalty for the creation of so many new objects, as shown in the example below.

String Concatenation Example:

public class Test {

    public static void main(String[] args){  
        long startTime = System.currentTimeMillis();
       
        String java = "Java";
        for (int i=0; i<10000; i++){  
            java = java + " is fun! Java";  
        }  
        System.out.println("Time taken by + operator concatenation: "
            +(System.currentTimeMillis()-startTime)+"ms");  
        startTime = System.currentTimeMillis();  
       
        StringBuilder sb = new StringBuilder("Java");  
        for (int i=0; i<10000; i++){  
            sb.append(" is fun! Java");  
        }    
        System.out.println("Time taken by StringBuilder concatentation: "
            +(System.currentTimeMillis()-startTime)+"ms");  
    }  
}

Example adapted from JavaTPoint

StringBuffer vs StringBuilder

  • Before JDK 5, StringBuffer was the only alternative to the String class.
    • StringBuilder was added to the language in Java 1.5
  • StringBuffer offers synchronization, meaning that it is thread-safe
    • Two threads cannot call methods on the same StringBuffer object simultaneously
  • StringBuilder is, therefore, the more efficient option when synchronization is not required.
    • None of the overhead required to make sure it is thread-safe.



  • Since we are not covering multi-threading in this course, we will focus on StringBuilder rather than StringBuffer.
    • As Oracle states "Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations."

StringBuilder Constructors:

  • There are several ways to construct a new StringBuilder:
public class Test {

    public static void main(String[] args){  
            StringBuilder sb1 = new StringBuilder();
            //constructs an empty StringBuilder with capacity of 16 characters
    
            String s = "Hello";
            StringBuilder sb2 = new StringBuilder(s); 
            //Constructs a StringBuilder with the same contents as s
            System.out.print(sb2);
    }  
}

  • The append method can be used to append data of any type to the end of the StringBuilder object.
  • When appending an object of another class, it will append the toString() representation of that object.
public class Test {

    public static void main(String[] args){ 
            StringBuilder sb1 = new StringBuilder();
           
            String s = "Hello";
            sb1.append(s);
           
            System.out.println(sb1);
           
            StringBuilder sb2 = new StringBuilder("World");
            sb1.append(sb2);
            sb1.append(true);
            sb1.append(2);
            sb1.append('K');
            //append a StringBuilder
            System.out.println(sb1);
    } 
}


  • The insert method will insert data of any type at a specified index in the StringBuilder's character array.
  • When inserting an object of another class, it will insert the toString() representation of that object.

public class Test {

    public static void main(String[] args){  
            StringBuilder sb1 = new StringBuilder("Hello");
            sb1.insert(2, "Mom");
            System.out.println(sb1);
            sb1.insert(5, 55);
            sb1.insert(3,  true);
            System.out.println(sb1);
    }  
}

  • Replaces the characters in a substring (index numbers within the String) of the sequence with characters in the specified String.
public class Test {

    public static void main(String[] args){ 
            StringBuilder sb1 = new StringBuilder("Hello");
            sb1.replace(2,4, "Mom");
            System.out.println(sb1);
    } 
}



CharAt, Length, IndexOf, Substring Methods

  • Just like the String class, StringBuilder also contains these familiar methods:

public class Test {

    public static void main(String[] args){ 
            StringBuilder sb1 = new StringBuilder("Hello");
            System.out.println("Length: " + sb1.length());
            System.out.println("First char: " + sb1.charAt(0));
            System.out.println("IndexOf l: " + sb1.indexOf("l"));
            System.out.println("Substring(0-5): " + sb1.substring(0, 4));
    } 
}

More Information:


Activity 17.1: My Name (10 pts)

  • This activity is adapted from a 36A activity, which you may recognize if you took this course from me.
  • Open a new Java class named MyName in Eclipse
  • We will create a program to greet the user by name.
  • Add a block comment at the top of your program with your names and section information.
/*
* @author
* CIS 36B, Activity 17.1
*/
  • At the top of the main method, let's declare our first StringBuilder variable - to store the first name of our user:
StringBuilder first_name;
  • Declare a second StringBuilder variable to store the last name of our user in the same _ style.
  • Declare a third StringBuilder variable to store the user's full name:
StringBuilder full_name;

  • Welcome the user with a statement like this one:
System.out.println("Hi! I want to learn your name!\n");
  • Now, prompt the user to enter their first name.
System.out.print("Please enter your first name: ");
  • Follow this prompt with a input.next() statement to capture the user input.
first_name = new StringBuilder(input.next());
  • Now prompt the user to enter his or her last name and store the input in the last_name variable.
  • We want to assign the full_name variable the value of the user's first and last name combined. Let's do so now using concatenation:
full_name = new StringBuilder(first_name.append(last_name));
  • Finally, let's greet the user by his or her full name.
System.out.println("Nice to meet you " + full_name + "!");

  • Run your program to ensure it is giving you the output you expect.
  • Next, let's calculate the length of the user's first and last names and output the result to the console:
System.out.println("The length of your first name is " + first_name.length() + " letters");
  • Now add a similar System.out.println statement to display the length of the user's last name AND full name (remember the full_name variable)
  • Next, let's return the user's initial's to them.
  • Let's declare a new StringBuilder variable called initials that you place at the top of your program with the other variable declarations.
StringBuilder initials = new StringBuilder();

  • Next, we are going to use the charAt() method to extract the initials from the user's first and last names.
  • A person's initials are composed of the first letters of their first and last names.
  • Therefore, we need the letters at position 0 in the first_name and last_name variables.
initials.append(first_name.charAt(???)); //finish this line to add full initials
  • Next, print the results to the console to display for the user.
System.out.println("Your initials are: " + initials);
  • Finally, we will add a title to the name (Mr, Ms or Mx):
  • Prompt the user to enter the preferred title:
      System.out.print("What title do you prefer?\nEnter Mr, Ms or Mx: ");
    String title = input.next();
    if (title.substring(0,2).equalsIgnoreCase("Mr")) {
        full_name.insert(0, "Mr. ");
    }

System.out.println("\nGoodbye, " + full_name + "!");
  • When you are finished, the output of your program should look like below.
  • However, look closely and you will see mistakes in my output.
  • Please correct the mistakes before you turn the program.
  • Submit your MyName.java program to Canvas.

The output of your program should look like this (except user input will vary):

Hi! I want to learn your name!

Please enter your first name: Jennifer
Please enter your last name: Parrish
Nice to meet you Jennifer Parrish!
The length of your first name is 16 letters
The length of your last name is 7 letters
The length of your full name is 16 letters
Your initials are: JP
What title do you prefer?
Enter Mr, Ms or Mx: Ms

Goodbye, Ms. Jennifer Parrish!

   
Wrap up
  • Answer the practice exam questions for this lesson on Canvas.


Upcoming Assignments

  • Activity 17.1 due Thursday at 11:59pm
  • Lab 9 due Monday at 11:59pm
  • Course Project due next Friday at 11:59pm
  • Quiz 7 due next Friday at 11:59pm