W3docs

How to Check if a String Contains a Substring in Java

Check for a substring in a Java string with contains, indexOf, startsWith, endsWith, and regex.

Checking whether one String appears inside another is one of the most common text tasks in Java. The right tool depends on what you actually need: a plain yes/no answer, the position of the match, an anchored check at the start or end, or a flexible pattern. This chapter walks through each idiomatic approach and when to reach for it.

The default: String.contains

When you only need a boolean — "is this fragment in there or not?" — contains is the clearest choice:

String text = "The quick brown fox";
boolean hasFox = text.contains("fox");   // true
boolean hasCat = text.contains("cat");   // false

contains accepts any CharSequence (so String, StringBuilder, etc.) and returns true if the argument occurs anywhere in the string. It is case-sensitive: text.contains("FOX") is false. One edge case worth remembering — the empty string is contained in every string, so text.contains("") is always true.

When you need the position: indexOf

contains is actually implemented on top of indexOf. If you need to know where a match starts (or want to scan for repeats), call indexOf directly:

String text = "The quick brown fox";
int at = text.indexOf("brown");   // 10
int no = text.indexOf("bird");    // -1

indexOf returns the zero-based index of the first match, or -1 when the substring is absent. The classic membership idiom is text.indexOf("brown") >= 0, which is equivalent to contains but also hands you the position for free. There is also lastIndexOf for searching from the end, and an overload that takes a starting offset for finding subsequent matches in a loop.

Anchored checks: startsWith and endsWith

If you specifically care about the beginning or end of a string — file extensions, URL prefixes, protocol schemes — startsWith and endsWith express the intent directly and read better than slicing:

String file = "report.pdf";
boolean isPdf  = file.endsWith(".pdf");      // true
boolean isHttp = "https://w3docs.com".startsWith("https://"); // true

These are faster and clearer than indexOf(prefix) == 0, because they stop comparing as soon as a character differs and never scan the whole string.

Case-insensitive and pattern matching

contains has no case-insensitive overload. The simplest fix is to normalise both sides:

boolean ci = text.toLowerCase().contains("FOX".toLowerCase()); // true

For more than a literal fragment — alternatives, wildcards, word boundaries — use a regular expression. Pattern.compile(...).matcher(text).find() returns true if the pattern matches anywhere, and CASE_INSENSITIVE handles casing without allocating lowercase copies:

import java.util.regex.Pattern;
boolean found = Pattern.compile("fox", Pattern.CASE_INSENSITIVE)
                       .matcher(text).find();
ApproachReturnsUse when
containsbooleanPlain membership, literal text
indexOfint (position, or -1)You need where the match is
startsWith / endsWithbooleanAnchored at start or end
Pattern.findbooleanPatterns, alternatives, case-insensitive

A worked example

This program runs the four approaches side by side over one sentence, including the case-sensitivity gotcha and the empty-string edge case.

java— editable, runs on the server

What to take from the run:

  • contains "brown" prints true and contains "cat" prints falsecontains is the direct boolean membership test for literal text.
  • contains "FOX" prints false even though the word "fox" is present, proving contains is case-sensitive; the normalised contains "FOX" (ci) line prints true.
  • indexOf "fox" prints 16, the zero-based start position of the match, while indexOf "bird" prints -1 to signal "not found" — that -1 is the sentinel you test against.
  • startsWith "The" and endsWith "dog" both print true, showing the anchored checks reading the very start and very end of the sentence.
  • contains "" prints true, the reminder that every string contains the empty string — guard against empty inputs if that would be a bug.

Practice

Practice
What does text.indexOf('bird') return when 'bird' is not present in the string text?
What does text.indexOf('bird') return when 'bird' is not present in the string text?
Was this page helpful?