In this Java tutorial, you will learn how to get the index of the nth occurrence of a substring in a string using String.indexOf(). The examples show both case-sensitive and case-insensitive searches, and explain what to return when the nth match is not present.
Java nth occurrence index using String.indexOf(String, fromIndex)
To find the index of the nth occurrence of a substring in a string, call String.indexOf() repeatedly and move the search start position after every match. The returned index is zero-based. If the substring is not found enough times, return -1.
A string, say str2, can occur in another string, say str1, many times. In a Java application, you may need the position of the first, second, third, or any nth occurrence of str2 in str1. The clean way to do this is to use the overloaded indexOf() method that accepts a starting index.
int index = text.indexOf(search, fromIndex);
Here, fromIndex tells Java where the next search should begin. After each successful match, update fromIndex and search again until the required occurrence is reached.
Recommended Java method to get nth occurrence of a substring
The following helper method finds the nth non-overlapping occurrence of a substring. It returns the starting index of that occurrence, or -1 when the substring does not occur that many times.
Example.java
public class Example {
public static void main(String[] args) {
String text = "java java java";
String search = "java";
int n = 3;
int index = nthIndexOf(text, search, n);
System.out.println("index of occurrence " + n + " = " + index);
}
public static int nthIndexOf(String text, String search, int occurrence) {
if (text == null || search == null) {
throw new IllegalArgumentException("text and search must not be null");
}
if (occurrence <= 0) {
throw new IllegalArgumentException("occurrence must be greater than zero");
}
if (search.isEmpty()) {
return 0;
}
int fromIndex = 0;
int index = -1;
for (int count = 1; count <= occurrence; count++) {
index = text.indexOf(search, fromIndex);
if (index == -1) {
return -1;
}
fromIndex = index + search.length();
}
return index;
}
}
Output
index of occurrence 3 = 10
In "java java java", the three occurrences of "java" start at indexes 0, 5, and 10. Therefore, the index of the third occurrence is 10.
Existing substring example: find the second occurrence of “ing”
In this example, we shall initialize two strings with variable names str1 and str2. And we are going to find the second occurrence of str2 in str1. You can change the value of n and observe the result.
Example.java
public class Example {
public static void main(String[] args) {
String str1 = "helloworld good morning good evening good night";
String str2 = "ing";
int n = 2;
int index = nthOccurrence(str1, str2, n);
System.out.println("index of str2 in str1 at occurrence "+ n +" = "+ index);
}
public static int nthOccurrence(String str1, String str2, int n) {
String tempStr = str1;
int tempIndex = -1;
int finalIndex = 0;
for(int occurrence = 0; occurrence < n ; ++occurrence){
tempIndex = tempStr.indexOf(str2);
if(tempIndex==-1){
finalIndex = 0;
break;
}
tempStr = tempStr.substring(++tempIndex);
finalIndex+=tempIndex;
}
return --finalIndex;
}
}
When the above program is run, the output to the console is as shown below.
Output
index of str2 in str1 at occurrence 2 = 33
The first "ing" appears in "morning", and the second "ing" appears in "evening". The method returns the starting index of the second match.
Case-insensitive nth occurrence search in Java
Sometimes the substring may appear with a different letter case. For example, you may want "GOOD", "Good", and "good" to be treated as the same search text. One simple approach is to convert both strings to lowercase before applying the nth occurrence logic.
Note that for the function, nthOccurrence(), we have added a fourth argument deciding whether to consider or ignore the case.
Example.java
public class Example {
public static void main(String[] args) {
String str1 = "helloworld good morning good evening good night";
String str2 = "GOOD";
int n = 2;
int index = nthOccurrence(str1, str2, n, true);
System.out.println("index of str2 in str1 at occurrence "+ n +" = "+ index);
}
public static int nthOccurrence(String str1, String str2, int n, boolean ignoreCase) {
if(ignoreCase) {
str1 = str1.toLowerCase();
str2 = str2.toLowerCase();
}
String tempStr = str1;
int tempIndex = -1;
int finalIndex = 0;
for(int occurrence = 0; occurrence < n ; ++occurrence){
tempIndex = tempStr.indexOf(str2);
if(tempIndex==-1){
finalIndex = 0;
break;
}
tempStr = tempStr.substring(++tempIndex);
finalIndex+=tempIndex;
}
return --finalIndex;
}
}
Output
index of str2 in str1 at occurrence 2 = 24
The search text is "GOOD", but the source string contains "good". Because ignoreCase is true, the method finds the second "good" occurrence and returns index 24.
Case-insensitive nth occurrence without changing the original strings
If you do not want to create lowercase copies of the strings, you can use regionMatches(). The following version compares each possible region while ignoring case, and returns the index of the nth non-overlapping match.
Example.java
public class Example {
public static void main(String[] args) {
String text = "Good morning, good evening, GOOD night";
String search = "good";
int n = 3;
int index = nthIndexOfIgnoreCase(text, search, n);
System.out.println("index of occurrence " + n + " = " + index);
}
public static int nthIndexOfIgnoreCase(String text, String search, int occurrence) {
if (text == null || search == null) {
throw new IllegalArgumentException("text and search must not be null");
}
if (occurrence <= 0) {
throw new IllegalArgumentException("occurrence must be greater than zero");
}
if (search.isEmpty()) {
return 0;
}
int found = 0;
int fromIndex = 0;
while (fromIndex <= text.length() - search.length()) {
if (text.regionMatches(true, fromIndex, search, 0, search.length())) {
found++;
if (found == occurrence) {
return fromIndex;
}
fromIndex += search.length();
} else {
fromIndex++;
}
}
return -1;
}
}
Output
index of occurrence 3 = 28
Overlapping and non-overlapping nth substring occurrences
Decide whether overlapping matches should be counted. This matters when the search substring can start inside a previous match.
- For
text = "aaaa"andsearch = "aa", non-overlapping matches start at indexes0and2. - For the same strings, overlapping matches start at indexes
0,1, and2.
For non-overlapping matches, update the next search position with index + search.length(). For overlapping matches, update it with index + 1.
// Non-overlapping search
fromIndex = index + search.length();
// Overlapping search
fromIndex = index + 1;
Return value when the nth substring occurrence is not found
A practical Java helper should clearly define its return value for missing matches. In the examples above, the method returns -1 when the requested nth occurrence is not available. This is consistent with the behavior of String.indexOf() when a match is not found.
- If
nis1, return the first occurrence index. - If
nis greater than the number of matches, return-1. - If
nis less than or equal to0, treat it as invalid input. - If the search substring is empty, handle it explicitly instead of letting the loop behave unexpectedly.
FAQs on getting the nth occurrence index in Java
How do I get the index of the nth occurrence of a substring in Java?
Use String.indexOf(search, fromIndex) inside a loop. Each time a match is found, update fromIndex and search again. When the loop reaches the required occurrence, return that index.
Does String.indexOf() return a zero-based index?
Yes. Java string indexes are zero-based. The first character is at index 0, so the returned value is the starting position of the matched substring in the source string.
What should a Java nth occurrence method return if the substring is not found?
A common choice is -1, because String.indexOf() also returns -1 when no match is found. The examples in this tutorial use -1 for missing nth occurrences.
How can I find the nth occurrence of a substring in Java ignoring case?
You can convert both strings to the same case before searching, or use regionMatches(true, ...) to compare regions while ignoring case. The regionMatches() approach avoids modifying or copying the original strings.
How do I count overlapping substring occurrences in Java?
After each match, set the next starting index to index + 1. If you want non-overlapping matches, set it to index + search.length() instead.
QA checklist for Java nth occurrence substring examples
- Confirm that every example states whether the search is case-sensitive or case-insensitive.
- Check that the returned index is zero-based and points to the beginning of the nth substring match.
- Verify the behavior when the requested occurrence is not present in the source string.
- Decide whether overlapping matches should be counted before using the helper method.
- Use
indexOf(search, fromIndex)for simple searches instead of repeatedly creating new substrings.
Summary: index of nth substring occurrence in Java
In this Java Tutorial, we have learned how to get the index of the nth occurrence of a substring in a string using String.indexOf(). For simple case-sensitive searches, loop with indexOf(search, fromIndex). For case-insensitive searches, either normalize both strings or use regionMatches(). Return -1 when the nth occurrence is not found.
TutorialKart.com