about | help
JavaBat java practice problems

JavaBat Java help pages:
If and Boolean Java Strings While and For Loops Arrays and Loops

Java String

This pages introduces the Java String class and chars with example code an exercises, in particular looking String methods charAt(), substring(), and indexOf(). See also the associated JavaBat live string problems, to practice String ideas or study for an exam. Written by Nick Parlante.

Java String Introduction

The Java String object contains a sequence char values (pronounced "car"). A char represents a single character, such as 'a' or 'Z' or 'µ' or '∑'. A char value is written in Java code using single quotes (') as shown here. Java supports the unicode character set, so we are no limited to just roman A-Z characters. The char type is a simple primitive type, very similar to int, so use simple = to copy char values, and == and != to compare char values. Rather than dealing with individual characters, you mostly deal with sequences of characters stored in a Java String object.

A string holds a sequence of characters, such as the string "Hello" or the string "It was the best of times. It was the worst of times.". A string can store a single word or the text of an entire book. Java's built in String class has many powerful and convenient features to operate on string data. Each String object stores a sequence of chars, such as "Hello", and implements methods that operate on those chars. We can create a String object the usual way with the "new" operator:

String str = new String("Hello");

Strings are so common in Java code that there is a special syntax to create them. You can create a String object simply by writing the desired text within double quotes "like this". The shorter version of the code below creates a new String object exactly as above.

String str = "Hello";

It's valid to create a string made of zero characters -- the quotes are right next to each other with nothing in between. This is known as the "empty string".

String empty = "";  // creates an empty string (zero chars)
The empty string is a valid string object, and the many of the operations described below work correctly on the empty string where it makes sense.

Special Characters

What if we want to create a string with a double quote (") in it? Java uses backslash (\) "escape" codes to insert special chars in a string, such as \" to get a double quote. Many computer languages use these same special backslash escape codes.

Testing a Character

The Character class has static utility methods that work on a single char:

String Concatenation +

When used between two int values, the + operator does addition. When used between two or more strings, the + operator appends the strings together to form a new, bigger string.
String start = "Hi";
String end = "coffee time!";

String result = start + " it's " + end; // result is "Hi it's coffee time!"
In computer science, the verb "concatenate" is used for this situation -- appending sequences together to make one big sequence. This special feature of the + operator also works when a string is combined with a primitive such as an int or double or char. The int or double value is automatically converted to string form, and then the strings are appended together. This feature of the + is very a convenient way to mix int and double values into a string:
int donutCount = 123;
char end = '!';

String result = "I ate " + donutCount + " donuts" + end;  // "I ate 123 donuts!"

String Immutable Style

Java string objects use the "immutable" style, which means that once a string object is created, its data never changes. For example, notice that the above uses of + concatenation do not change existing strings. Instead, the + creates and returns new strings, leaving the originals intact. As we explain the many string methods below, notice that no method changes an existing string. The immutable style is popular since it keeps things simple.

Basic String Methods

The Java String class has many useful methods.

Using Basic String Methods

Methods like trim() and toLowerCase() always return new string objects to use; they never change the receiver string object (this is the core of "immutable" style -- the receiver object never changes). For example, the code below does not work:
String word = "  hello  ";
word.trim();  // ERROR, this does not change word
// word is still "  hello  ";
When calling trim() (or any other string method) we must use the result returned by the method, assigning into a new variable with = for example:
String word = "  hello  ";
String trimmed = word.trim();  // Ok, trimmed is "hello"
If we do not care about keeping the old value of the string, we can use = to assign the new value right into the old variable:
String word = "  hello  ";
word = word.trim();  // Ok, word is "hello" (after the assignment)
This works fine. The trim() method returns a new string ("hello") and we store it into our variable, forgetting about the old string.

String Comparison

Given two string objects, use the equals() method to check if they contain the same characters. In Java, you typically use the equals() method to compare two objects -- strings are just an example of that rule. The == operator is similar but is used most often to compare primitives such as int and char. In general, use equals() to compare objects, and use == to compare primitives. Unfortunately, using == with string objects will compile fine, but at runtime it will not actually compare the strings (the == checks if the two pointers point to the same object). It's easy to accidentally use == with objects instead of equals(), so it is a common error. The equals() method follows the pointers to the two String objects and compares them char by char to see if they are the same. This is sometimes called a "deep" comparison -- following the pointers and looking at the actual objects. The comparison is "case-sensitive" meaning that the char 'A' is considered to be different from the char 'a'.
String a = "hello";
String b = "there";

// Correct -- use the .equals() method
if (a.equals("hello")) {
  System.out.println("a is \"hello\"");
}

// NO NO NO -- do not use == with Strings
if (a == "hello") {
  System.out.println("oops");
}

// a.equals(b) -> false
// b.equals("there") -> true
// b.equals("There") -> false
// b.equalsIgnoreCase("THERE") -> true
There is a variant of equals() called equalsIgnoreCase() that compares two strings, ignoring uppercase/lowercase differences. If you want to ignore uppercase/lowercase differences in your application, another solution is to covert all strings to, say, lowercase with toLowerCase() when they come into the system.

String also includes the handy startsWith()/endsWith() methods that test if one string matches the start or end of another:

String str = "hello";
str.endsWith("llo") -> true
str.startsWith("he") -> true
str.startsWith("hx") -> false
str.startsWith("") -> true (note, empty string is true)

String Comparison Ordering

The string compareTo(String other) methods compares the receiver string object against passed in string, returning a negative int if the receiver is less, 0 if the strings are the same, and a positive int if the receiver is greater. For example comparing the string "apple" to other strings:
String a = "apple";
a.compareTo("zebra") → -1
a.compareTo("apple") → 0
a.compareTo("aaa") → +1
The example shows a return values of -1/+1. However, in reality, compareTo() can returns a more complex int value reflecting the first char where the strings differ, but the sign of the returned int will be -1/0/+1 as shown here.

There is also a compareToIgnoreCase() comparison method that ignores uppercase/lowercase differences.

String Index Numbers

The chars in a String are each identified by an index number, from 0 .. length-1. The leftmost char is at index 0, the next at index 1, and so on, like this:
String str = "Hello";

This "zero based" indexing style is very common in computer science for identifying elements in a collection. The method charAt(int index) returns an individual char from inside a string (see also the substring() method below). The valid index numbers are in the range 0..length-1. Using an index number outside of that range will raise a runtime exception and stop the program at that point.

String string = "hello";
char a = string.charAt(0);  // a is 'h'
char b = string.charAt(4);  // b is 'o'
char c = string.charAt(string.length() - 1);  // same as above line
char d = string.charAt(99);  // ERROR, index out of bounds

String Substring

The substring() method is a way of picking out a sub-part of string. It uses index numbers to identify the part of the string you want. The simplest version of substring() takes a single int index value and returns a new string made of the chars starting at that index and extending through the end of the string:
String string = "hello";
String a = string.substring(2);  // a is "llo"
String b = string.substring(3);  // b is "lo"
The more complex substring(int start, int end) method takes both start and end index numbers, returning a string of the chars between start and one before end:
String string = "Hello";
String a = string.substring(2, 4);  // a is "ll" (not "llo")
String b = string.substring(0, 3);  // b is "Hel"
Remember that substring() goes up to but does not include the end index. The length of the result is (end - start). It's easy to make off-by-one errors with index numbers in any algorithm. Make a little drawing of a sample string with its index numbers to get your code exactly right.

String indexOf()

The indexOf() method searches inside the receiver string for a "target" string. The indexOf() method returns the index number where the target string is first found (searching left to right), or -1 if the target is not found. The indexOf() search is case-sensitive -- upper and lowercase letters must match exactly.
String string = "Here there everywhere";

int a = string.indexOf("there");  // a is 5
int b = string.indexOf("er");     // b is 1
int c = string.indexOf("eR");     // c is -1, "eR" is not found

String indexOf() Other Versions

There are a few different versions of indexOf() that are more powerful than the basic version:

String Parsing

"Parsing" is the process of taking a string from a file or the network or the user, and processing it to extract the information we want. A common strategy is to use a few calls to indexOf() to figure out the index numbers of something interesting inside the string. Then use substring() to pull out the desired part of the string. After processing the data, we can use + to reassemble the parts to make a new string.

Suppose we have a string that contains some text with a pair parenthesis somewhere inside of it, like this: "It was hot (darn hot!) I'm telling you". Suppose we want to fix the string so that the part in parenthesis is in all upper case. We can use two calls to indexOf() to find the '(' and ')', and substring to extract the text. Example code:

String string = "It was hot (so hot!) I'm telling you.";
int left = string.indexOf("(");
int right = string.indexOf(")");

// pull out the text inside the parens
String sub = string.substring(left+1, right); // sub is "so hot!"

sub = sub.toUpperCase();  // sub is "SO HOT!"

// Put together a new string
String result = 
  string.substring(0, left+1) +   // It was hot (
  sub +                           // SO HOT!
  string.substring(right);        // ) I'm telling you.

// result is "It was hot (SO HOT!) I'm telling you."

String Code Examples

Example 1

Given a string, returns a string made of repetitions of that string. This code demonstrates using + to assemble a larger string in a loop:
public String repeat(String string, int count) {
  String result = "";
  for (int i=0; i<count; i++) {
    result = result + string;
  }
  return result;
}

Example2

Given a string, returns how many '!' chars it contains. This code demonstrates using a for loop, calling length() and charAt() to look at all the chars in a string:
public String countExclaim(String string) {
  int count = 0;
  for (int i=0; i<string.length(); i++) {
    if (string.charAt(i) == '!') count++;
  }
  return count;
}

Example 3

Given a string where the string "OOP" appears at least two times, find the first and last OOP in the whole string. Return the text from between the two OOP. Demonstrates using indexOf() and substring():
public String oopPair(String string) {
  int start = string.indexOf("OOP");
  int end = string.lastIndexOf("OOP");
  return string.substring(start+1, end);
}

Example 4

Suppose you have a string like this:"Once there was a woman name:angelina: and a man name:tony: and their freind name:jane: and ...". Inside of a long text there are little "name:" sections. Write code to find and print all the names. Demonstrates a more complex use of indexOf() and substring() in a loop to parse a string:
public void printNames(String string) {
  int i = 0;
  while (true) {
    int found = string.indexOf("name:", i);
    if (found == -1) break;
    int start = found + 5; // start of actual name
    int end = string.indexOf(":", start);
    System.out.println(string.substring(start, end));
    i = end + 1;  // advance i to start the next iteration
  }
}

javabat.com java learning. Copyright 2006 Nick Parlante.