1. Overview
There are many ways to check if a String contains a substring. In this article, we’ll be looking for substrings within a String while focusing on case-insensitive workarounds to String.contains() in Java. Most importantly, we’ll provide examples of how to solve this issue.
2. The Simplest Solution: String.toLowerCase
The simplest solution is by using String.toLowerCase(). In this case, we’ll transform both strings to lowercase and then use the contains() method:
assertTrue(src.toLowerCase().contains(dest.toLowerCase()));
We can also use String.toUpperCase() and it would provide the same result.
3. String.matches With Regular Expressions
Another option is by using String.matches() with regular expressions:
assertTrue(src.matches("(?i).*" + dest + ".*"));
The matches() method takes a String to represent the regular expression. (?i) enables case-insensitivity and .* uses every character except line breaks.
4. String.regionMatches
We can also use String.regionMatches(). It checks if two String regions match, using true for the ignoreCase parameter:
public static boolean processRegionMatches(String src, String dest) {
for (int i = src.length() - dest.length(); i >= 0; i--)
if (src.regionMatches(true, i, dest, 0, dest.length()))
return true;
return false;
}
assertTrue(processRegionMatches(src, dest));
To improve the performance, it starts matching the region, taking into account the length of the destination String. Then, it diminishes the iterator.
5. Pattern With the CASE_INSENSITIVE Option
The java.util.regex.Pattern class provides us a way of matching strings using the matcher() method. In this case, we can use the quote() method to escape any special characters, and the CASE_INSENSITIVE flag. Let’s take a look:
assertTrue(Pattern.compile(Pattern.quote(dest), Pattern.CASE_INSENSITIVE)
.matcher(src)
.find());
6. Apache Commons StringUtils.containsIgnoreCase
Finally, we’ll take advantage of the Apache Commons StringUtils class:
assertTrue(StringUtils.containsIgnoreCase(src, dest));
7. Performance Comparison
As in this general article about checking for substrings using the contains method, we used the open-source framework Java Microbenchmark Harness (JMH) to compare the performance of the methods in nanoseconds:
- Pattern CASE_INSENSITIVE Regular Expression: 399.387 ns
- String toLowerCase: 434.064 ns
- Apache Commons StringUtils: 496.313 ns
- String Region Matches: 718.842 ns
- String matches with Regular Expression: 3964.346 ns
As we can see, the winner is Pattern with the CASE_INSENSITIVE flag enabled, closely followed by toLowerCase(). We also noticed a clear improvement in the performance between Java 8 and Java 11.
8. Conclusion
In this tutorial, we looked at a few different ways to check a String for a substring, while ignoring the case in Java.
We looked at using String.toLowerCase() and toUpperCase(), String.matches(), String.regionMatches(), Apache Commons StringUtils.containsIgnoreCase(), and Pattern.matcher().find().
Also, we evaluated the performance of each solution and found that using the compile() method from java.util.regex.Pattern with the CASE_INSENSITIVE flag performed the best*.*
As always, the code is available over on GitHub.