String Manipulation
Why this matters
Imagine you're building a simple welcome screen for a new app. You want it to greet users by name, maybe something like, "Welcome back, Priya!" Or think about a game that needs to display a score: "Your score: 4500". How does the program take the static text "Welcome back, " and combine it with a variable username? How does it take "Your score: " and attach a number that changes?
This is where String manipulation comes in. It's not just about storing text; it's about actively working with it—chopping it up, sticking it together, and searching through it. These are fundamental skills you'll use in almost every program you write. We'll explore how Java handles text and the powerful, built-in tools it gives you to manage it.
Concept overview
flowchart TD
A[Start: String fullName = "Maya Angelou"] --> B{Get first initial}
B --> C["firstInitial = fullName.substring(0, 1) --> 'M'"]
C --> D{Find the space}
D --> E["spaceIndex = fullName.indexOf(' ') --> 4"]
E --> F{Get last name}
F --> G["lastName = fullName.substring(spaceIndex + 1) --> 'Angelou'"]
G --> H{Combine and convert to lowercase}
H --> I["username = (firstInitial + lastName).toLowerCase()"]
I --> J[End: "mangelou"]
Core explanation
Hello! I'm Saavi, and I'm excited to walk you through one of the most useful tools in your Java toolkit: the String class. You'll use strings constantly, so let's build a strong foundation.
What is a String?
At its heart, a String is an object that represents a sequence of characters. You've already been using them!
String greeting = "Hello, world!";
String school = "Boston High School";
These are called string literals. They are the most common way to create a String. You can also use the String class constructor, but it's less common:
String name = new String("Carlos");
Good news: The String class is part of a package called java.lang, which is automatically imported into every Java program. You never have to write an import statement to use String.
The Most Important Rule: Strings are Immutable
This is a concept that trips up many students, so let's focus on it. String objects in Java are immutable. This means that once a String object is created, it can never be changed.
Think of a String like a message written in permanent marker on a small whiteboard. If you have a whiteboard that says "Seattle," you can't just erase the "S" and make it "eattle."
If you want to make a change, you have to grab a brand new whiteboard and write the new word on it. The original "Seattle" whiteboard still exists, unchanged.
Look at this code:
String city = "Seattle";
city.toLowerCase(); // This method returns a new string "seattle"
System.out.println(city); // What does this print?
Many people expect this to print "seattle". But it will print "Seattle"! The toLowerCase() method didn't change the original city string. It created and returned a new string, "seattle," which we didn't save.
To "change" our variable, we have to reassign it to the new string that was created:
String city = "Seattle";
city = city.toLowerCase(); // city now points to the NEW string "seattle"
System.out.println(city); // This prints "seattle"
Combining Strings: Concatenation
"Concatenation" is a fancy word for joining strings together. Java makes this easy with the + operator.
String firstName = "Aaliyah";
String lastName = "Smith";
String fullName = firstName + " " + lastName; // "Aaliyah Smith"
int score = 95;
String report = "Your score is: " + score; // "Your score is: 95"
<figure class="lesson-figure"><div class="shr-widget" data-shr-widget="{"type":"array_animation","label":"Concatenating 'Your score is: ' + 95","steps":[{"label":"Initial strings","values":["Your score is: ","95"],"highlight":[0,1]},{"label":"Result of concatenation","values":["Your score is: 95"],"highlight":[0]}],"values":["Your score is: ","95"],"highlight":[0,1]}" aria-label="An animation showing 'Your score is: ' being combined with the integer 95 to form the string 'Your score is: 95'."></div><figcaption class="lesson-figure-caption">String Concatenation: Joining text and numbers.</figcaption></figure>
You can also use the += operator, which is just a shortcut:
String message = "Happy ";
message += "Thanksgiving!"; // message is now "Happy Thanksgiving!"
Using String Methods to Get Information
Since we can't change strings, we need tools to read them and create new ones based on them. These tools are the String methods. To understand them, you first need to understand indexing.
Characters in a string are numbered starting from 0.
For the string String s = "Hello";
His at index 0eis at index 1lis at index 2lis at index 3ois at index 4
The last index is always length() - 1. Trying to access an index outside this range (like -1 or 5 in this case) will crash your program with a StringIndexOutOfBoundsException.
Here are the key methods you must know for the AP exam:
int length()
Returns the number of characters in the string.
String team = "Bulls";
int len = team.length(); // len is 5
String substring(int from, int to)
This is one of the most powerful and most confusing methods. It extracts a new string from the original.
from: The starting index (inclusive).to: The ending index (exclusive).
String message = "AP Computer Science";
// Indices: 0123456789...
String comp = message.substring(3, 11); // "Computer"
It starts at index 3 (C) and ends just before index 11 (` `).
String substring(int from)
A simpler version that extracts from the from index all the way to the end of the string.
String message = "AP Computer Science";
String sci = message.substring(12); // "Science"
By the way, if you need to get a single character as a String, you can use substring(index, index + 1).
String name = "Jordan";
String firstLetter = name.substring(0, 1); // "J"
int indexOf(String str)
Searches for the first occurrence of str inside your string and returns the starting index. If it's not found, it returns -1.
String sentence = "The quick brown fox.";
int foxIndex = sentence.indexOf("fox"); // 16
int dogIndex = sentence.indexOf("dog"); // -1
boolean equals(Object other)
This is the only correct way to check if two strings have the exact same sequence of characters.
String pass1 = "password123";
String pass2 = "Password123";
String pass3 = "password123";
pass1.equals(pass2); // false (it's case-sensitive)
pass1.equals(pass3); // true
Never use == to compare the contents of strings. We'll cover why in the Common Mistakes section.
int compareTo(String other)
Compares two strings lexicographically (like in a dictionary).
- Returns
< 0ifthisstring comes beforeother. - Returns
0if the strings are identical. - Returns
> 0ifthisstring comes afterother.
String a = "apple";
String b = "banana";
String c = "apple";
a.compareTo(b); // returns a negative number
b.compareTo(a); // returns a positive number
a.compareTo(c); // returns 0
This is useful for sorting lists of strings.
See it in action
Worked examples
Let's apply these concepts to a couple of realistic problems.
Creating a Student ID
Problem: A school in Dallas needs to generate student IDs. The format is the first letter of the first name, the full last name, and the last two digits of their graduation year, all in lowercase. Given a student's first name, last name, and graduation year, create their ID.
Student Data:
- First Name:
Marcus - Last Name:
Jones - Graduation Year:
2025
Solution Walkthrough:
- 1Store the initial dataLet's start by putting our data into variables.
String firstName = "Marcus"; String lastName = "Jones"; int gradYear = 2025; - 2Get the first initialWe need the first character of
firstName. We can get this usingsubstring(0, 1).String firstInitial = firstName.substring(0, 1); // "M" - 3Get the last two digits of the yearThis is a number, but we need it as a
String. A clever way is to first convert the number to a string, then take a substring of that.String yearString = "" + gradYear; // A shortcut to convert int to String: "2025" String yearDigits = yearString.substring(2); // "25"Why this works: Concatenating an empty string
""with the integer2025forces Java to convert the integer to the string"2025". Then,substring(2)gets everything from index 2 to the end. - 4Combine the piecesNow we just concatenate the parts in the right order: initial + last name + year digits.
a String studentId = firstInitial + lastName + yearDigits; // "MJones25" - 5Convert to lowercaseThe requirement is for the ID to be all lowercase. We can call the
toLowerCase()method on our final result. Remember, this creates a new string!studentId = studentId.toLowerCase(); // "mjones25"Final Code:
String firstName = "Marcus"; String lastName = "Jones"; int gradYear = 2025; String firstInitial = firstName.substring(0, 1); String yearString = "" + gradYear; String yearDigits = yearString.substring(2); String studentId = firstInitial + lastName + yearDigits; studentId = studentId.toLowerCase(); System.out.println(studentId); // Prints "mjones25"
Validating an Email
Problem: Write code that checks if a given String email contains an "@" symbol and if it ends with ".com".
Solution Walkthrough:
- 1Store the email
String email = "[email protected]"; - 2Check for the "@" symbolThe
indexOf()method is perfect for this. If it finds "@", it will return its index (a number 0 or greater). If not, it returns -1.boolean hasAtSign = email.indexOf("@") >= 0; // true if found, false if notWhy
>= 0? We don't care where the "@" is, just that it exists.indexOfreturns -1 only when the substring isn't found. So any non-negative result means it's there. - 3Check for the ".com" endingThis is a bit trickier. We can't just use
indexOf(".com")because that would be true for"test.com.net". We need to check the end of the string. A great way to do this is to extract the last 4 characters and see if they equal ".com".// First, make sure the string is long enough to have a ".com" boolean endsWithCom = false; if (email.length() >= 4) { String ending = email.substring(email.length() - 4); endsWithCom = ending.equals(".com"); }Why
email.length() - 4? If the email is[email protected](length 18), we want to start our substring at index 14 to get the last 4 characters.18 - 4 = 14. This is a reliable pattern for getting the end of a string. - 4Combine the checksThe email is valid for our purposes only if both conditions are true.
boolean isValid = hasAtSign && endsWithCom; System.out.println("Is valid email? " + isValid); // Prints "Is valid email? true"
Try it yourself
Ready to practice? Here are a couple of challenges. Try to solve them on your own before looking up a solution.
1. Format an Address
You are given three strings: city ("Chicago"), state ("IL"), and zipCode ("60654"). Write code to combine them into a single, formatted string that looks exactly like this: Chicago, IL 60654.
Hint: Remember that you can concatenate strings with other strings, including literals like ", " and " ".
2. Extract a Username from a URL
You are given a string representing a social media profile URL: String url = "https://www.social.com/profile/sofia_g". Your task is to extract just the username (sofia_g) from the end of the URL. You can assume the username always comes after the last /.
Hint: The indexOf method can find the first occurrence of a character. Is there a way to find the last one? (Look up lastIndexOf if you're curious, or think how you could use substring and indexOf together).
Practice — 8 questions
In simple terms, string manipulation is about how to create, combine, and work with pieces of text (called Strings) in your Java code using built-in tools.
String greeting = "Hello, world!";
String school = "Boston High School";
- 1.15.A: Develop code to create string objects and determine the result of creating and combining strings.
- 1.15.B: Develop code to call methods on string objects and determine the result of calling these methods.
- 1.15.A.1
- A String object represents a sequence of characters and can be created by using a string literal or by calling the String class constructor.
- 1.15.A.2
- The String class is part of the java.lang package. Classes in the java.lang package are available by default.
- 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.
- 1.15.A.4
- Two String objects can be concatenated together or combined using the + or += operator, resulting in a new String object. A primitive value can be concatenated with a String object. This causes the implicit conversion of the primitive value to a String object.
- 1.15.A.5
- A String object can be concatenated with any object, which implicitly calls the object's toString method (a behavior that 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.
- 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 a StringIndexOutOfBoundsException.
- 1.15.B.2
- The following String methods—including what they do and when they are used—are part of the Java Quick Reference: • 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) returns the index of the first occurrence of str; returns -1 if not found. • boolean equals(Object other) returns true if this corresponds to the same sequence of characters as other; returns false otherwise. • 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.
- 1.15.B.3
- A string identical to the single element substring at position index can be created by calling substring(index, index + 1).
flowchart TD
A[Start: String fullName = "Maya Angelou"] --> B{Get first initial}
B --> C["firstInitial = fullName.substring(0, 1) --> 'M'"]
C --> D{Find the space}
D --> E["spaceIndex = fullName.indexOf(' ') --> 4"]
E --> F{Get last name}
F --> G["lastName = fullName.substring(spaceIndex + 1) --> 'Angelou'"]
G --> H{Combine and convert to lowercase}
H --> I["username = (firstInitial + lastName).toLowerCase()"]
I --> J[End: "mangelou"]
Read what Saavi narrates
(Sound of a gentle, welcoming synth chord)
Hello! I'm Saavi, and welcome to Shrutam.
Imagine you're building a simple welcome screen for a new app. You want it to greet users by name, maybe something like, "Welcome back, Priya!" Or think about a game that needs to display a score: "Your score: 4500". How does the program take the static text "Welcome back, " and combine it with a variable username?
This is where String manipulation comes in. A String in Java is simply a sequence of characters, like a word or a sentence. Today, we're going to learn how to create them, combine them, and use Java's built-in tools to work with them.
Let's walk through a quick example. A school in Dallas needs to generate student IDs. The format is the first letter of the first name, the full last name, and the last two digits of their graduation year, all in lowercase. Let's say we have Marcus Jones, graduating in 2025.
First, we'd get his first initial, "M", using the substring method. Then, we'd take his last name, "Jones". For the year, we can convert the number 2025 into the text "2025", and then use substring again to grab just the "25".
We combine those pieces... "M" plus "Jones" plus "25" gives us "MJones25". Finally, the school wants it in lowercase, so we call one more method to get our final result: "mjones25". See how we took different pieces of information and stitched them together? That's the power of string manipulation.
Now, here's one of the most common mistakes I see students make. When you want to check if two strings are the same, like checking a password, it's very tempting to use the double equals sign, like you would with numbers. But for Strings, this is wrong. The double equals sign checks if two variables are the exact same object in memory, not if they have the same text inside.
Instead, you must always, always use the dot-equals method. So, `password.equals("secret123")`. Using dot-equals compares the actual characters in the string. Getting this right will save you from so many headaches down the road.
You're building a really important skill here. Keep practicing, stay curious, and you'll be great.
(Outro chord)
`==` checks if two variables point to the *exact same object* in memory. It does NOT check if two different string objects contain the same characters.
Always use `string1.equals(string2)` to compare the actual character sequences of two strings.
Calling a method like `myString.toUpperCase()` does not change `myString`. It creates and returns a *new* string. If you don't assign this new string to a variable, the result is lost.
If you want to "change" a string, reassign the variable: `myString = myString.toUpperCase();`.
Students often forget that the `to` index is exclusive. `myString.substring(0, 5)` gives you characters at indices 0, 1, 2, 3, and 4. It does *not* include the character at index 5.
Remember the analogy: "from the start index, up to (but not including) the end index." To get `N` characters starting at `from`, the second argument is `from + N`.
`indexOf` is an `int` method, not `boolean`. It returns the integer `-1` when the substring is not found. A condition like `if (myString.indexOf("a"))` will not compile.
Check the return value against -1. For example: `if (myString.indexOf("a") != -1)` or `if (myString.indexOf("a") >= 0)`.
Trying to get the first character with `myString.substring(1, 2)` will actually get the *second* character. This leads to incorrect results and bugs that are hard to find.
Burn it into your memory: first character is index 0, second is index 1, and the last is `length() - 1`.
This happens when you try to access an index that doesn't exist, like `myString.substring(myString.length())`. The highest valid index is `myString.length() - 1`.
Before calling `substring` or other index-based methods, double-check your logic. Make sure your indices are within the valid range of `0` to `length() - 1`.