Explain Codes LogoExplain Codes Logo

String contains - ignore case

java
performance
best-practices
null-checks
Nikita BarsukovbyNikita Barsukov·Nov 7, 2024
TLDR

To check if a String contains another String regardless of case, convert both of them to lower or upper case with toLowerCase()/toUpperCase() before using contains(), or opt for Pattern with CASE_INSENSITIVE:

String str = "Hello World!"; String searchStr = "world"; // Because 'Case' should never come between a 'String' and its 'contains' boolean containsIgnoreCase = str.toLowerCase().contains(searchStr.toLowerCase()); // When Regex is not a just a tin can for a string boolean containsRegex = Pattern.compile(Pattern.quote(searchStr), Pattern.CASE_INSENSITIVE).matcher(str).find(); System.out.println("Ignoring cases, it contains: " + containsIgnoreCase); System.out.println("Even Regex is case blind here: " + containsRegex);

Note the usage of toLowerCase()/toUpperCase() for direct comparison and Pattern with CASE_INSENSITIVE for pattern matching.

The artillery from Apache Commons

Getting tired of writing long conversion checks? Pack an artillery from Apache Commons Lang and use StringUtils.containsIgnoreCase:

boolean containsIgnoreCase = StringUtils.containsIgnoreCase(str, searchStr);

This method is not only forgiving to your fingers, but also your system's performance, skillfully sidestepping the heavyweight regex and providing a neat, readable approach especially when you've got the commons library.

Acing the null checks

No matter which method you are implementing, make sure you aced the null checks to steer clear of NullPointerExceptions:

if (str != null && searchStr != null) { // perform your magical case-insensitive check }

Or you can even sit back and let Apache Commons Lang do the heavy lifting for you:

boolean containsIgnoreCase = StringUtils.containsIgnoreCase(str, searchStr);

The containsIgnoreCase method coolly handles null inputs, returns false and doesn't throw a tantrum (read: exceptions).

Performance considerations

Do remember to check your performance pulse while you are at it. Converting strings to lower or upper case might get resource-greedy, creating new objects for longer strings.

But don't worry, using Pattern with precompiled regex will come to your rescue especially for frequent tasks:

Pattern pattern = Pattern.compile(Pattern.quote(searchStr), Pattern.CASE_INSENSITIVE); boolean containsIgnoreCase = pattern.matcher(str).find();

Here, Pattern.quote() is the saviour when the search string might have some regex special characters. But remember, not all heroes wear capes, ditch it when not necessary for better performance.

We've got Regex, the DIY way!

Not a fan of external dependencies? Can't stand the thought of regex performance? Then String.regionMatches is your pick:

public static boolean containsIgnoreCase(String str, String searchStr) { if (str == null || searchStr == null) return false; final int length = searchStr.length(); if (length == 0) return true; for (int i = str.length() - length; i >= 0; i--) { if (str.regionMatches(true, i, searchStr, 0, length)) { return true; } } return false; }

Here, we are using the trusty regionMatches method to compare regions of the string, as cool as ice to case sensitivity, without having to rely on external libraries or converting the entire strings to a single case.

When you're building your invincible case-insensitive search functionality, be sure to consider the search string length:

  • A bigger search string might steal away your matches.
  • On the other hand, a shorter search string could give you more false positives than you can handle.

Factor in the frequency and the circumstances of the search operation:

  • For high-frequency or heavy-duty use, equip yourself with precompiled regex patterns.
  • For the less-intensive tasks, toLowerCase()/toUpperCase() combined with contains() offers a well-balanced blend of simplicity and performance.

And finally, for a friend who is never wrong, benchmark your options in your specific use case context and let that guide your selection.