Explain Codes LogoExplain Codes Logo

Find the Number of Occurrences of a Substring in a String

java
prompt-engineering
best-practices
performance
Nikita BarsukovbyNikita Barsukov·Nov 3, 2024
TLDR

To swiftly identify the number of substring occurrences within a string, employ Java's String.indexOf() within a loop. Remember, you need to update the index each time to explore the string's remainder. Here's how to do it:

public int countOccurrences(String str, String sub) { int count = 0; // Power scanning loop - hands ready for celebration 🎉 for (int idx = 0; (idx = str.indexOf(sub, idx)) != -1; idx += sub.length()) count++; return count; }

Just invoke countOccurrences("example", "am") to get your quick result—1.

Apache Commons Lang to the rescue

For cleaner and more understandable code, use StringUtils.countMatches from Apache Commons Lang. This existing method strips the complexities:

public int countOccurrences(String str, String sub) { //Put StringUtils to work. Let's save those keystrokes. return StringUtils.countMatches(str, sub); }

Before leaping into this, remember to include the Apache Commons library in your project dependencies.

Fancy Stream and regex approach

Exploit Java Streams and regular expressions to gain more fine control:

public long countOccurrencesWithStream(String str, String regex) { Pattern pattern = Pattern.compile(regex); // Streams and regex - the dynamic duo return pattern.splitAsStream(str).count() - 1; }

With this approach, double-check that the regex is formatted and escaped.

Always update your index

Properly updating the index after each match ensures that you avoid infinite loops and keep away from the stormy seas of errors. If the lastIndex is -1, throw a lifebuoy, and don't proceed.

The split trick

The split method with a negative limit is an undercover agent:

public int countOccurrencesWithSplit(String str, String sub) { // Split's got your back 🕵️‍ return str.split(Pattern.quote(sub), -1).length - 1; }

Manual iteration, who? Not with split. Subtract one because the initial split isn't a match.

Accurate algorithm validation

Ensure your method hits the target every single time. Test it with different cases: edge cases, no matches, empty strings, substrings at the start or end of the string – everything.

Performance deliberations

Spaghetti code isn't the tastiest. Find a method that balances simple, readable and performant. Sure, StringUtils and regex solutions are often more digestible, but large strings or complex patterns may slow them down.

Efficiency meets readability

Writing your algorithm, remember that built-in methods can provide the perfect mix of readability and efficiency, starving off unnecessarily complex loops.