1.15 - String Manipulation
A
String object represents a sequence of characters. You can create one with a string literal, or by calling the String class constructor directly. String lives in java.lang, so no import is needed.String a = "hello"; // using a string literal String b = new String("hello"); // using the constructor
Strings are immutable, meaning once a
String object is created, it can never be changed. Any method you call on a string doesn’t modify the original, it just returns a new string.You can combine strings using
+ or +=, which creates a brand new String object. You can even concatenate a primitive value with a string, Java will automatically convert it to a string first.String greeting = "Hello" + " " + "World"; // "Hello World" int age = 16; String message = "I am " + age + " years old"; // primitive gets converted automatically
The
+ operator works left to right, so where the numbers sit matters. Once a String is involved, + means join, not add:System.out.println("Sum: " + 2 + 3); // Sum: 23 System.out.println(2 + 3 + " is the sum"); // 5 is the sum System.out.println("Sum: " + (2 + 3)); // Sum: 5 System.out.println("Total: " + 4.5 + " " + true); // Total: 4.5 true String word = "dove"; word += "s"; // word is now "doves", a new String object
You can also concatenate a string with any object, and Java will call that object’s
toString() method behind the scenes (every class inherits this from Object). toString() returns a string representation of that object. Subclasses often override toString() with their own version, a concept called method overriding, where a subclass method shares a signature with a superclass method but behaves differently. Note: actually overriding toString() yourself is outside the scope of this course.Dog myDog = new Dog("Rex"); System.out.println("My dog: " + myDog); // calls myDog.toString() automatically
If
Dog doesn’t override toString, it uses the version from Object, which gives the class name, an @, and a code (something like Dog@1b6d3586). If Dog does override it, you get whatever its toString returns. Printing an object with System.out.println(myDog) calls toString too.String Indexing
A string’s index values run from
0 to one less than its length. Trying to access an index outside that range throws a StringIndexOutOfBoundsException.String word = "cat"; // valid indices are 0, 1, and 2 (length() is 3) String letter = word.substring(3, 4); // StringIndexOutOfBoundsException, there's no index 3
String Methods (Java Quick Reference)
int length() // number of characters in the string String substring(int from, int to) // substring from index "from" up to (not including) "to" String substring(int from) // same as substring(from, length()) int indexOf(String str) // index of first occurrence of str, -1 if not found boolean equals(Object other) // true if same sequence of characters int compareTo(String other) // <0 if this comes before other, 0 if equal, >0 if after
Example usage:
String phrase = "Hello World"; int len = phrase.length(); // 11 String sub1 = phrase.substring(0, 5); // "Hello" String sub2 = phrase.substring(6); // "World" int index = phrase.indexOf("World"); // 6 boolean same = phrase.equals("Hello World"); // true int compare = phrase.compareTo("Hello Universe"); // positive, since "World" > "Universe" alphabetically
Remember, strings are immutable. A method like
substring hands back a new string and leaves the original alone. To keep the result, you have to store it, often back in the same variable:String bird = "doves"; bird.substring(1); // returns "oves", but the result is never stored System.out.println(bird); // doves bird = bird.substring(1); // bird now refers to a new String, "oves" System.out.println(bird); // oves
Note: using
.equals() to compare a String against something that isn’t a String is outside the scope of this course.You can grab a single character (as a one character string) at a given position by calling
substring(index, index + 1).String word = "cat"; String firstLetter = word.substring(0, 1); // "c"
To get the last character, start one before the end:
word.substring(word.length() - 1) gives "t". In Unit 2 you’ll use substring(i, i + 1) inside loops to look at a string one character at a time.Substring Bounds
For
substring(from, to), the character at index from is included, but the character at index to is not, so the result always has to - from characters. The indices have to make sense: from can’t be negative, to can’t be more than length(), and from can’t be more than to. Break any of those rules and you get a StringIndexOutOfBoundsException.Two edge cases are legal and trip people up:
to can equal length() (that’s how you reach the last character), and from can equal to, which gives the empty string "".String word = "planet"; // indices 0 to 5, length() is 6 String mid = word.substring(2, 5); // "ane" (indices 2, 3, 4), 5 - 2 = 3 characters String last = word.substring(5, 6); // "t", to can equal length() String none = word.substring(3, 3); // "", from equals to String rest = word.substring(6); // "", same as substring(6, 6) String bad1 = word.substring(4, 7); // StringIndexOutOfBoundsException, 7 > length() String bad2 = word.substring(4, 2); // StringIndexOutOfBoundsException, from > to
Finding Text with indexOf
indexOf searches from the start of the string and returns the index where the first match begins. It’s case sensitive, and it returns -1 when there’s no match, so -1 tells you the text isn’t there.String fruit = "banana"; int a = fruit.indexOf("an"); // 1, the first "an" starts at index 1 int b = fruit.indexOf("nan"); // 2 int c = fruit.indexOf("A"); // -1, there's no uppercase "A"
indexOf pairs well with substring when you need the text before or after a marker:String email = "dove@library.org"; int at = email.indexOf("@"); // 4 String user = email.substring(0, at); // "dove", stops right before the @ String domain = email.substring(at + 1); // "library.org", starts right after the @
Comparing Strings with equals and compareTo
To check whether two strings have the same characters, use
equals. It’s case sensitive, so "Dove" and "dove" are not equal. Don’t use == for this. With objects, == checks whether two variables refer to the exact same object (more in 2.6), and two different String objects can hold the same characters.String a = "Dove"; String b = new String("Dove"); // a separate String object with the same characters boolean sameText = a.equals(b); // true, same sequence of characters boolean sameObject = (a == b); // false, two different objects boolean caseMatters = a.equals("dove"); // false, "D" and "d" are different characters
compareTo tells you which string comes first in alphabetical order. Only the sign of the result matters: negative means the string you called it on comes first, 0 means they’re equal, and positive means it comes after. If one string is the start of the other, the shorter one comes first.int r1 = "apple".compareTo("banana"); // negative, "apple" comes before "banana" int r2 = "cat".compareTo("cat"); // 0, same characters int r3 = "cat".compareTo("catalog"); // negative, "cat" is the start of "catalog" int r4 = "zebra".compareTo("apple"); // positive, "zebra" comes after "apple"
Careful: Java really compares character codes, and every uppercase letter comes before every lowercase letter, so
"Zebra".compareTo("apple") is negative. Keep the case the same when you want true alphabetical order.Putting It Together
Here’s a trace that uses several methods at once. Try to work out each value before reading the comments.
String name = "Ada Lovelace"; int space = name.indexOf(" "); // 3 String first = name.substring(0, space); // "Ada" String last = name.substring(space + 1); // "Lovelace" String initials = first.substring(0, 1) + last.substring(0, 1); // "AL" System.out.println(last + ", " + first); // Lovelace, Ada System.out.println(initials + " " + name.length()); // AL 12
Note: the Java Quick Reference lists one more
String method, split. It comes up in 4.6 (Using Text Files), since it returns an array.