Skip to main content
Logo image

Section 7.1 Manipulating strings

We first encoutered the String type in SectionΒ 2.2Β Text output since we have to use strings if we want to generate text output. In that section we mostly looked at how to write String literals in double quotes and how to use the concatenation operator + to combine literal String values with the String representations of other kinds of values.
In this section we’ll go into a few more details about the concatenation operator and then look at instance methods that we can use to slice and dice the text of strings and to compare strings to each other.

Subsection 7.1.1 A bit more string concatenation

We used string concatention in SectionΒ 2.2Β Text output to generate formatted strings to be printed out. As we saw then a + expression where one of the values is a String results in a new String formed by concatenating (smooshing together) the string representation of both values.
Like the arithmetic + operator, there’s also a compound assignment version, += that updates String variable to a new String consisting of its old value plus the string representation of the value being added.
String s = "hello";
s += ", world!";
System.out.println(s); // prints "hello, world!"
It’s important to note that like the arithmetic version String += changes the variable, not the String itself. In fact String values are immutable, meaning once a String is created, its text cannot be changed. When we add two Strings (or a String and another value converted to a String) we get a new String without making any change to the values being added together just like when we add the int values 1 + 2 the original 1 and 2 aren’t changed. When we use += we are making a new String by adding something to the current value of a variable and then assigning that new value back into the variable, again just like with numbers.

Activity 7.1.1. Happy birthday greeting.

Try the following code. Add another variable, lastname, with the value "Hernandez". Use += or + to add the lastname variable after name to result. Then use += or + to add two more exclamation points (!) to the end of the happy birthday greeting in result. Note that you will need to add a space between name and lastname to get the correct output.

Activity 7.1.2.

Given the following code segment, what is in the string referenced by s1?
String s1 = "xy";
String s2 = s1;
s1 = s1 + s2 + "z";
  • s1 will equal "xy" plus another "xy" then z at the end.
  • xyxyz
  • s1 contains the original value, plus itself, plus "z"
  • xy xy z
  • No spaces are added during concatenation.
  • No spaces are added during concatenation, and an additional "xy" should be included at the beginning.
  • s1 was set to "xy" initially, so the final answer will be "xyxyz"

Activity 7.1.3.

What do you think the following will print? Guess before you hit run. If you want the addition to take place before the numbers are turned into a string what should you do? Try to modify the code so that it adds 4 + 3 before appending the value to the string. Hint: you used this to do addition before multiplication in arithmetic expressions.
Since the same operators are processed from left to right this will print 1243. First 4 will be turned into a string and appended to 12 and then 3 will be turned into a string and appended to 124. If you want to do addition instead, try using parentheses!

Subsection 7.1.2 String lengths and character indices

So far we’ve been using as String values as atomic values that we can print or concatenate with other strings to produce bigger strings. But it’s also possible to treat a String as a sequence of individual characters.
For instance, thinking about a string in terms of a sequence of characters raises questions like, how long is it? The answer in Java is the length of a string is the number of characters in it, including any spaces or other special characters. The string shown below is fourteen characters long.
Then we can think about the position of each character in a String. The position of each character is called its index which is a number that says how many positions away from the front of the String it is. That means that unlike in English, but like many other programming languages (but not Snap!), indices start at zero, rather than one, since the first character is zero positions from the front of the String.
Note that because the first character is at index 0, the last character’s index is one less than the length of the string. So in a fourteen-character string like the one diagramed below, the last index is 13.
a string with the position (index) shown above each character
Figure 7.1.1. A string with length 14 with the index of each character shown below it.

Subsection 7.1.3 String instance methods

So that’s fine but how do we actually use the length of a string or the index of a character in a program? This brings us to one of the big differences between primitive types and classes like String.
With primitive types the only things we can do with them is compute new values using operators or pass them to methods like the Math methods we learned about in SectionΒ 3.3Β The Math class (which then compute new values using operators).
To do things with String values we instead use instance methods which are like the methods we learned about in SectionΒ 3.1Β Writing methods but attached to the specific object so it has access to the data that makes up that object’s value. When we call a method with the dot operator, we say we call or invoke it on the object referenced by the expression to the left of the dot. The method then has access to the actual data that makes up the referenced object.
For example there’s a length method defined in the String class that returns the the String’s length. The number it returns depends on the specific String we call it on.
// Invoking length on the literal string "hello". Prints 5
System.out.println("hello".length());

// Invoking length on the literal string "boo". Prints 3.
System.out.println("boo".length());

// Invoking length on the value of the variable x. Prints 5.
String x = "hello";
System.out.println(x.length());

// Invoking length on the value of a string concatenation expression. Prints 12.
System.out.println((x + ", fred!").length());
The String class includes a ton of methods but for the AP exam, you only need to know how to use the methods we look at below. They are all also decribed in the AP CSA Java Quick Reference Sheet that you have access to during the exam.

Subsection 7.1.4 Slicing and dicing with length, substring, and indexOf

With a couple more methods we will have all the tools we need to take apart strings to extract interesting parts or to determine if strings contain certain text.
To get a part of an existing String we use the substring method which takes two int arguments specifying the part of the original string to extract. For instance "abcdef".substring(2, 5) returns the "cde" which is made up the characters starting at index 2 of "abcdef" and ending at (but not including) index 5.
Remember that String objects are immutable so the original String isn’t changed. Instead substring method returns a new String that contains a copy of some of the same text.
The first argument to substring must be a valid index into the string and the second must either be a valid index or the length of the string. If either argument is invalid the method will crash with a StringIndexOutOfBoundsException.
Perhaps the easiest way to understand both arguments to substring is to think of them as specifying where to cut the string to extract the substring. If we had the string shown below on a strip piece of paper, to cut out the substring(5, 9) we’d cut at the line just before box 5 and again just before box 9, giving us the shaded substring "is a".
a string with the position (index) shown above each character
Figure 7.1.2. Cutting substring(5, 9) out of "This is a test".
Note that this also works for 0, which just means β€œcut” before the first character in the string and for the length of the string, which means β€œcut” just before the non-existant character that would be at that position. Here are some more examples.
String s = "This is a test";
s.substring(0, 1);                       // "T"
s.substring(1, 2);                       // "hi"
s.substring(0, 4);                       // "This"
s.substring(4, 4);                       // ""
s.substring(0, s.length());              // "This is a test"
s.substring(10, s.length());             // "test"
s.substring(s.length() - 3, s.length()); // "est"
Note how we can use any expression that produces an int as either argument to substring, such as s.length() - 3 and s.length() in the last example. That also means if we had a variable, i, that held a valid index into a string s we could get a String containing the one character at that index with the substring call s.substring(i, i + 1).

Activity 7.1.4. Fix out of bounds bugs.

The following code crashes with a StringIndexOutOfBoundsException because the arguments to substring aren’t valid. Can you fix the code by changing the arguments for the substring method to print out the substring "o"?
If substring is for when we want to extract a substring from a particular position in a String, the method indexOf method is kind of the opposite, allowing us to find the position where a particular substring occurs in a String. We call the method on the string we want to search in (sometimes called the haystack) and pass the string whose text we are looking for (the needle) as an argument and the method returns the index indicating the position where the needle is found in the haystack. If the needle doesn’t occur in the haystack it returns -1.
String haystack = "abcdef";
haystack.indexOf("a");   // 0
haystack.indexOf("abc"); // also 0
haystack.indexOf("b");   // 1
haystack.indexOf("f");   // 5
"abc".indexOf(haystack); // -1, longer String can't be in a shorter one
haystack.indexOf("xyz"); // -1, not found
We can use indexOf when we are taking apart strings to find the index of some particular piece of text which we can then pass to substring to extract the text before or after it. For instance, if we had a text containing the first paragraph of a book we could extract the first sentence with an expression like this:
paragraph.substring(0, paragraph.indexOf(". ") + 1);
The call to indexOf finds the index of the first period followed by a space. (This does assume that the first sentence doesn’t end in a exclamation point or a question mark.) The resulting index is where the period is. That index plus one, is used as the second argument to a call to substring which then extracts everything from index 0 up to and including the period.

Activity 7.1.5.

Run the code below to see the output from the String methods length, substring, and indexOf. How many letters does substring(0, 3) return? What does indexOf return when its argument is not found?

Activity 7.1.6.

What is the value of pos after the following code executes?
String s1 = "abccba";
int pos = s1.indexOf("b");
  • The first character is at index 0 in a string.
  • The method indexOf returns the first position of the passed str in the current string starting from the left (from 0).
  • Does indexOf start from the left or right?
  • Does the string contain a b?

Activity 7.1.7.

What is the value of len after the following code executes?
String s1 = "baby";
int len = s1.length();
  • Length returns the number of characters in the string, not the number of characters in the name of the variable.
  • The position of the last character is 3, but the length is 4.
  • Length returns the number of characters in the string.
  • Length is never negative.

Activity 7.1.8.

What is the value of s2 after the following code executes?
String s1 = "baby";
String s2 = s1.substring(0,3);
  • This would be true if substring returned all the characters from the first index to the last inclusive, but it does not include the character at the last index.
  • This would be true if it was s1.substring(0,1)
  • This would be true if it was s1.substring(0,2)
  • Substring returns all the characters from the starting index to the last index -1.

Activity 7.1.9.

What is the value of s2 after the following code executes?
String s1 = "baby";
String s2 = s1.substring(2);
  • The method substring(index) will return all characters starting the index to the end of the string.
  • This would be true if it was substring(1);
  • This would be true if it was substring(1,2);
  • This would be true if it was substring(2,3);
  • This would be ture if it was substring(0,2);

Subsection 7.1.5 String comparison with equals and compareTo

In SectionΒ 4.3Β Where do booleans come from? we learned comparison operators that work on primitive types such as ==, <, and >. We also mentioned that we can’t really use them with String values. Technically we can use == but it probably doesn’t do what we want for reasons we’ll discuss in SubsectionΒ 9.2.2Β Comparing Objects and we can’t use use < or > at all.
However, with reference types like String, we must use methods instead of operators. In particular we need to use the method equals instead of == and compareTo instead of any of the relational operators <, <, >, and >=.
The equals method compares the text of two Strings objects and returns true if the text is the same and false otherwise. The reason == might not work the way we want is because it just compares two references, i.e. where in memory the referenced String objects live. It’s possible to have two distinct String objects whose data is stored in two different places in memory but which contain the same sequence of characters. According to == those references are not the same (because they live in different places in memory) but according to equals they are same because the sequences of characters are the same.
The compareTo method compares two String objects, one being the String we invoked the method on, and the other being the single argument passed to the method. It compares the text of both Strings character by character the way we would if we were putting them into an dictionary. So "aardvark" comes before "acme" which comes before "zoologist". The return value of compareTo is an int that indicates the ordering between the String we invoked compareTo on (call that the first string) and the argument String (the second string) by the following scheme:
  • If the text of the two strings is the same, compareTo returns zero.
  • If the first string should be ordered before the second string, compareTo returns a negative number.
  • If the first string should be ordered after the second string, compareTo returns a positive number.
That may be a bit hard to wrap your head around but this table shows that we can translate an expression using any of the four relational operators to an expression that compares the value returned by compareTo to 0 using that same operator.
What we want to write What we write instead
a < b a.compareTo(b) < 0
a <= b a.compareTo(b) <= 0
a > b a.compareTo(b) > 0
a >= b a.compareTo(b) >= 0

Activity 7.1.10.

Run the code below to see the output from compareTo and equals. Since "Hello!" would be alphabetically ordered after "And", compareTo returns a positive number. Since "Hello!" would be alphabetically ordered before "Zoo", compareTo returns a negative number.
Is equals case-sensitive? When does compareTo return a negative number?
There are lots of other methods in the String class. You can look through the Java documentation for the String class online. You don’t have to know all of these for the exam, but you can use them if you want to on the exam.

Activity 7.1.11.

Activity 7.1.12.

Activity 7.1.13.

What is the value of answer after the following code executes?
String s1 = "Hi";
String s2 = "Bye";
int answer = s1.compareTo(s2);
  • positive (> 0)
  • H is after B in the alphabet so s1 is greater than s2.
  • The method compareTo will only return 0 if the strings have the same characters in the same order.
  • negative (< 0)
  • This would be true if it was s2.compareTo(s1)

Subsection 7.1.6 Coding Challenge: Pig Latin

pig latin
Can you speak Pig Latin? In Pig Latin, you take the first letter and put it at the end of the word and add the letters β€œay” to the end. For example, β€œpig” becomes β€œigpay”.
Create a program that takes a word and transforms it to Pig Latin using String methods. You may need the word’s length, a substring that does not include the first letter, and a substring that is just the first letter (you can get the ith letter of a string using substring(i,i+1) so for example the letter at index 3 would be substring(3,4)).

Project 7.1.14.

Write code in the pigLatin method below to use the substring method to transform a word given as its argument into Pig Latin where the first letter is put at the end and β€œay” is added. The word pig is igpay in Pig Latin. Change the input below to try it on other words.

Subsection 7.1.7 Bonus Challenge: Unicode

If you get done early with the previous challenge, here’s something else fun you can do in Java, although it’s not covered in the AP exam.
Java was one of the first programming languages to use UNICODE for its characters rather than ASCII. While ASCII could represent 128 characters which was plenty for English, Unicode is an international standard that tries to assign a number (which they like to call a β€œcodepoint”) to every character in every language. Unicode codepoints are traditionally represented in hex code (a base 16 code that uses the digits 0-9 and the letters A-F for 10-15), so you might see things like U+1F600. But they’re just numbers. That last one is the same as 128512.
When Java was released in an 1996, Unicode had been around for five years and the Unicode people had declared they would only ever need \(2^{16}\) or 65,536 code points to represent all the characters used in the world. So Java included a char data type that can hold exactly \(2^{16}\) values. Then, seven months later, the Unicode folks, said, β€œOoops, that’s not enough”, and extended their system to its current size of 1,112,064 possible codepoints. (As of September 2024, 154,998 codepoints have actually been assigned characters. The next version of Unicode, which should be released in September 2025, is expected to have 159,845 assigned codepoints.)
That made char kind of obsolete. But while not every Unicode codepoint can be represented in a Java char, you can use an int to represent a codepoint and the method Character.toString to translate an int into a String containing the character for that codepoint. (You might see older Java code that casts numbers to char. For many codepoints that will work but not on more recently added codepoints including, critically, those for Emoji. 😞 So better to use Character.toString and ignore char altogether.)

Project 7.1.15. Unicode challenge.

Try the following program which prints out an English β€œA”, a Chinese character, and an emoji. Then look up other characters at this Unicode Lookup site and change the code to print them out. (Use the Dec column in site to get the decimal number.) Can you print out letters from three different languages?

Subsection 7.1.8 Summary

  • (AP 1.15.A.1) A String object represents a sequence of characters and can be created by using a string literal.
  • (AP 1.15.A.2) The String class is part of the java.lang package. Classes in the java.lang package are available by default.
  • String objects can be created by using string literals (String s = β€œhi”;) or by calling the String class constructor (String t = new String(β€œbye”);).
  • (AP 1.15.A.3) A String object is immutable, meaning once a String object is created, its attributes cannot be changed. Methods called on a String object do not change the content of the String object.
  • (AP 1.15.A.4) Two String objects can be concatenated together or combined using the + or += operator, resulting in a new String object.
  • (AP 1.15.A.4) A primitive value can be concatenated with a String object. This causes the implicit conversion of the primitive value to a String object.
  • (AP 1.15.A.5) A String object can be concatenated with any object, which implicitly calls the object’s toString method (a behavior which is guaranteed to exist by the inheritance relationship every class has with the Object class). An object’s toString method returns a string value representing the object. Subclasses of Object often override the toString method with class-specific implementation. Method overriding occurs when a public method in a subclass has the same method signature as a public method in the superclass, but the behavior of the method is specific to the subclass. Overriding the toString method of a class is outside the scope of the AP CSA exam.
  • index - A number that represents the position of a character in a string. The first character in a string is at index 0.
  • length - The number of characters in a string.
  • substring - A new string that contains a copy of part of the original string.
  • (AP 1.15.B.1) A String object has index values from 0 to one less than the length of the string. Attempting to access indices outside this range will result in an IndexOutOfBoundsException.
  • (AP 1.15.B.2) The following String methods and constructors, including what they do and when they are used, are part of the AP CSA Java Quick Reference Sheet that you can use during the exam:
    • String(String str) : Constructs a new String object that represents the same sequence of characters as str.
    • int length() : returns the number of characters in a String object.
    • String substring(int from, int to) : returns the substring beginning at index from and ending at index (to -1).
    • String substring(int from) : returns substring(from, length()).
    • int indexOf(String str) : searches for str in the current string and returns the index of the first occurrence of str; returns -1 if not found.
    • boolean equals(Object other) : returns true if this (the calling object) is equal to other; returns false otherwise. Using the equals method to compare one String object with an object of a type other than String is outside the scope of the AP CSA exam.
    • int compareTo(String other) : returns a value < 0 if this is less than other; returns zero if this is equal to other; returns a value > 0 if this is greater than other. Strings are ordered based upon the alphabet.
  • str.substring(index, index + 1) returns a single character at index in string str.

Subsection 7.1.9 AP Practice

Activity 7.1.16.

What is the value of s2 after the following code executes?
String s1 = new String("hi there");
int pos = s1.indexOf("e");
String s2 = s1.substring(0,pos);
  • hi th
  • The substring method returns the string starting at the first index and not including the last index. The method indexOf returns the index of the first place the string occurs.
  • hi the
  • This would be correct if substring returned all characters between the first index and last index, but does it?
  • hi ther
  • This would be correct if indexOf returned the last position the string str was found in the current string, does it?
  • hi there
  • This would be correct if indexOf returned the last position the string str was found in the current string and if substring included all characters between the start and end index. Check both of these.

Activity 7.1.17.

What is the value of s1 after the following code executes?
String s1 = "Hi";
String s2 = s1.substring(0,1);
String s3 = s2.toLowerCase();
  • Strings are immutable, meaning they don’t change. Any method that changes a string returns a new string. So s1 never changes.
  • This would be true if the question was what is the value of s2 and it was substring(0,2) not (0,1)
  • This would be true if the question was what is the value of s2, not s1.
  • This would be true if the question was what is the value of s3, not s1.
You have attempted of activities on this page.