TheDeveloperBlog.com


Java

Java IndexOf, lastIndexOf Search Strings

IndexOf. A String possibly contains a matching value. With indexOf, we can search it, from the start, for a match. This works with char and String arguments.


LastIndexOf. This method searches from the rightmost index of a String. And both methods can start searching at a nonzero index, specified as an integer argument.


A simple example. This program uses indexOf with character arguments. The three indexOf calls locate indexes of the chars b, d, and z (which is not found).

Not found: For the letters "b" and "d," the indexes 1 and 3 are returned. But for "z," negative one is returned: no "z" is found.

Based on:

Java 7

Java program that uses indexOf

public class Program {
    public static void main(String[] args) {

	String line = "abcd";

	int b = line.indexOf('b');
	System.out.println(b);

	int d = line.indexOf('d');
	System.out.println(d);

	int f = line.indexOf('z');
	System.out.println(f);
    }
}

Output

1
3
-1

LastIndexOf. This method searches from the last char moving to the first char of the source string. So it locates first the final instance of a char or substring.

Note: As with indexOf, lastIndexOf can accept a String and a starting index as arguments. It mirrors indexOf in these ways.

Java program that uses lastIndexOf

public class Program {
    public static void main(String[] args) {

	String line = "mom";

	// Get index of last "m".
	int m = line.lastIndexOf('m');
	System.out.println(m);
    }
}

Output

2

IndexOf, string. Finding a char within a String is useful. But finding a substring or multiple-character sequence is often more helpful. IndexOf (and lastIndexOf) supports this.

Also: We can pass a start index optionally to these methods to restrict our search field.

Java program that uses indexOf, string argument

public class Program {
    public static void main(String[] args) {

	String line = "one two three";

	// Get index of substring two.
	int index = line.indexOf("two");
	System.out.println(index);
    }
}

Output

4

While-loop. We often use indexOf within a loop. Consider this program. It continues call indexOf as it advances the position. It finds all instances of the two-char string.

While
Java program that uses indexOf, while-loop

public class Program {
    public static void main(String[] args) {

	String data = "abcabcabc";

	// Keep looping until -1 encountered.
	int pos = 0;
	while ((pos = data.indexOf("ab", pos)) != -1) {
	    // Print position and the substring starting at it.
	    System.out.println(pos);
	    System.out.println(data.substring(pos));
	    pos++;
	}
    }
}

Output

0
abcabcabc
3
abcabc
6
abc

Null argument error. We must be careful with indexOf when we might have null Strings. If we pass it a null argument, it will throw a NullPointerException.

Java program that causes NullPointerException

public class Program {
    public static void main(String[] args) {

	String data = "welcome";
	int j = data.indexOf(null); // Cannot do this.
	System.out.println(j);
    }
}

Output

Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.indexOf(Unknown Source)
    at java.lang.String.indexOf(Unknown Source)
    at program.Program.main(Program.java:7)

Between, before, after. We can use indexOf and lastIndexOf to extract parts of strings relative to other substrings. Some reusable methods are helpful.

Between, Before, After

Benchmark. In this test, we find that a call to indexOf is faster than a for-loop with calls to charAt. When possible, indexOf is preferable to for-loops. It locates chars faster.

Here: This program searches the "input" string for the lowercase "m." The first part uses indexOf. The second, for and charAt.

Java program that times indexOf, charAt

public class Program {
    public static void main(String[] args) {

	String input = "abcdefghijklm";
	long t1 = System.currentTimeMillis();

	// Version 1: use indexOf to locate character.
	for (int i = 0; i < 10000000; i++) {
	    int index = input.indexOf('m');
	    if (index < 0) {
		System.out.println("Error");
	    }
	}

	long t2 = System.currentTimeMillis();

	// Version 2: use for, charAt to locate character.
	for (int i = 0; i < 10000000; i++) {
	    int index = -1;
	    for (int x = 0; x < input.length(); x++) {
		if (input.charAt(x) == 'm') {
		    index = x;
		    break;
		}
	    }
	    if (index < 0) {
		System.out.println("Error");
	    }
	}

	long t3 = System.currentTimeMillis();

	// ... Times.
	System.out.println(t2 - t1);
	System.out.println(t3 - t2);
    }
}

Results

 61 ms, indexOf
172 ms, for loop, charAt

Benchmark, lastIndexOf. Sometimes we can use lastIndexOf as an optimization. If a substring occurs 0 or 1 times in a String, indexOf and lastIndexOf return the same result.

And: If, based on our data, we find that the value occurs near the end more often, lastIndexOf is a faster yet equal method.

Here: The character "8" occurs near the end of a String. IndexOf requires more time to find it than lastIndexOf.

Java that times indexOf, lastIndexOf

public class Program {
    public static void main(String[] args) {

	String input = "0123456789";
	long t1 = System.currentTimeMillis();

	// Version 1: use indexOf.
	for (int i = 0; i < 10000000; i++) {
	    int index = input.indexOf('8');
	    if (index < 0) {
		System.out.println(false);
	    }
	}

	long t2 = System.currentTimeMillis();

	// Version 2: use lastIndexOf.
	for (int i = 0; i < 10000000; i++) {
	    int index = input.lastIndexOf('8');
	    if (index < 0) {
		System.out.println(false);
	    }
	}

	long t3 = System.currentTimeMillis();

	// ... Times.
	System.out.println(t2 - t1);
	System.out.println(t3 - t2);
    }
}

Results

41 ms, indexOf
14 ms, lastIndexOf

String occurrence count. With indexOf and a while-loop we can count occurrences of one string within a source string. We introduce a countStringOccurrences method.

String Occurrence Method

ArrayList. Strings have an indexOf method. But so do other classes like ArrayList. We use most indexOf methods in the same way: we test -1 to see if nothing was found.

ArrayList: indexOf

With charAt, and a loop, we can search Strings without indexOf. But indexOf, a declarative method call, uses fewer statements. It may be (and often is) easier to read, debug and test.


Checking for negatives is a challenging part of using indexOf and lastIndexOf. We must handle -1 in a special case. Errors occur if we use an unchecked return value from indexOf.