Java String contains(): Check for Substrings
- String.contains() is case-sensitive. For case-insensitive contains, use str.toLowerCase(Locale.ROOT).contains(query.toLowerCase(Locale.ROOT)).
- Both the string and the argument must be non-null. Use a null check before calling contains() on any string that might be null.
- Use indexOf(str) when you need the position as well as presence β contains() only returns true/false.
contains() is in the top 20 Java String methods by frequency of use. It's also in the top 10 sources of NullPointerException in production Java code. Understanding the null contract and the case-sensitivity behaviour up front prevents the bugs I see repeatedly in code review.
contains() Usage, Case-Insensitive Variant, and Null Safety
String.contains() takes a CharSequence (which String implements) and returns true if the argument appears anywhere within the string. The check is case-sensitive. For case-insensitive contains, convert both strings to the same case first β but use Locale.ROOT or Locale.ENGLISH to avoid locale-specific case conversion bugs (the Turkish 'i' problem).
package io.thecodeforge.strings; import java.util.Objects; public class StringContainsExample { public static void main(String[] args) { String serviceName = "io.thecodeforge.payment.PaymentRetryService"; // Basic contains β case-sensitive System.out.println(serviceName.contains("payment")); // false β capital P System.out.println(serviceName.contains("Payment")); // true System.out.println(serviceName.contains("Retry")); // true // Case-insensitive contains String query = "PaymentRetry"; boolean caseInsensitive = serviceName.toLowerCase(java.util.Locale.ROOT) .contains(query.toLowerCase(java.util.Locale.ROOT)); System.out.println("Case-insensitive: " + caseInsensitive); // true // Null safety β contains() throws NPE if called on null OR passed null String nullString = null; // Safe null check pattern boolean safeCheck = nullString != null && nullString.contains("Payment"); System.out.println("Safe null check: " + safeCheck); // false, no NPE // Or use Objects utility boolean objectsCheck = Objects.toString(nullString, "").contains("Payment"); System.out.println("Objects check: " + objectsCheck); // false // contains() vs indexOf() β when you need the position int position = serviceName.indexOf("PaymentRetry"); System.out.println("Position: " + position); // 33 (0-indexed) // contains() returns true/false only; use indexOf() when you need index // Check if string contains any of multiple substrings String log = "ERROR: NullPointerException in PaymentService"; boolean isError = log.contains("ERROR") || log.contains("FATAL"); System.out.println("Is error: " + isError); // true } }
true
true
Case-insensitive: true
Safe null check: false
Objects check: false
Position: 33
Is error: true
| Method | Returns | Case-sensitive? | Use When |
|---|---|---|---|
| contains(str) | boolean | Yes | Simple substring presence check |
| indexOf(str) >= 0 | boolean (derived) | Yes | Need both presence and position |
| toLowerCase().contains() | boolean | No (manual) | Case-insensitive contains |
| matches(regex) | boolean | Configurable | Pattern-based containment check |
| startsWith(str) | boolean | Yes | Check only the beginning |
| endsWith(str) | boolean | Yes | Check only the end |
π― Key Takeaways
- String.contains() is case-sensitive. For case-insensitive contains, use str.toLowerCase(Locale.ROOT).contains(query.toLowerCase(Locale.ROOT)).
- Both the string and the argument must be non-null. Use a null check before calling contains() on any string that might be null.
- Use indexOf(str) when you need the position as well as presence β contains() only returns true/false.
- For checking multiple substrings, use contains() chained with || for simple cases or a stream with anyMatch() for a list of patterns.
β Common Mistakes to Avoid
- βCalling contains() on a potentially null string β always null-check first. str.contains() on a null reference throws NullPointerException.
- βPassing null to contains() β contains(null) also throws NullPointerException. The argument must be non-null.
- βCase-sensitive contains when the data is user input β user input is unpredictable case. Always normalise to the same case before comparing.
- βUsing contains() in a tight loop on large strings β contains() is O(n*m). For repeated searches in large text, consider using indexOf() with a starting position to scan progressively, or Aho-Corasick for multi-pattern matching.
Interview Questions on This Topic
- QHow would you implement a case-insensitive substring check in Java?
- QWhat's the difference between String.contains() and String.indexOf()?
Frequently Asked Questions
How do I do a case-insensitive contains in Java?
There's no built-in case-insensitive contains. The standard approach is to convert both strings to the same case: str.toLowerCase(Locale.ROOT).contains(query.toLowerCase(Locale.ROOT)). Use Locale.ROOT to avoid locale-specific case conversion issues.
Does Java String contains() throw a NullPointerException?
Yes, in two cases: if the string you're calling contains() on is null (calling a method on null), or if you pass null as the argument to contains(). Both throw NullPointerException. Always null-check before calling contains() on any string that might be null.
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.