patternjavaMinor
Checking whether a string contains a substring only once
Viewed 0 times
oncesubstringcheckingcontainsonlywhetherstring
Problem
I want to check if a string contains only a single occurrence of the given substring (so the result of
or
Can you suggest a simpler/more efficient implementation?
containsOnce("foo-and-boo", "oo") should be false). In Java, a simple and straightforward implementation would be eitherboolean containsOnce(final String s, final CharSequence substring) {
final String substring0 = substring.toString();
final int i = s.indexOf(substring0);
return i != -1 && i == s.lastIndexOf(substring0);
}or
boolean containsOnce(final String s, final CharSequence substring) {
final String substring0 = substring.toString();
final int i = s.indexOf(substring0);
if (i == -1) {
return false;
}
final int nextIndexOf = s.indexOf(substring0, i + 1);
return nextIndexOf == 0 || nextIndexOf == -1; // nextIndexOf is 0 if both arguments are empty strings.
}Can you suggest a simpler/more efficient implementation?
Solution
Perhaps using pattern matching. It looks more readable to me, but I have no idea about which is more efficient.
Also note that
Note: you can also write it as
I don't know which of the two is more readable.
EDIT:
After looking up whichever is faster: indexof vs matcher
It seems to be the general consensus that indexof is a bit faster, but that we're talking about such low times that it really doesn't matter much.
Go for whichever solution you prefer I guess ...
public static boolean containsOnce(final String s, final CharSequence substring) {
Pattern pattern = Pattern.compile(substring.toString());
Matcher matcher = pattern.matcher(s);
if(matcher.find()){
return !matcher.find();
}
return false;
}
public static void main(String[] args) throws Exception {
System.out.println(containsOnce("aba","a")); //false
System.out.println(containsOnce("abab", "ab")); //false
System.out.println(containsOnce("aba", "b")); //true
System.out.println(containsOnce("aaa", "aa")); //true
System.out.println(containsOnce("","")); //true
System.out.println(containsOnce("ab","")); //false
}Also note that
containsOnce("aaa","aa") returns true. Not sure if you would count this as correct or not.Note: you can also write it as
Pattern pattern = Pattern.compile(substring.toString());
Matcher matcher = pattern.matcher(s);
return matcher.find() && !matcher.find();I don't know which of the two is more readable.
EDIT:
After looking up whichever is faster: indexof vs matcher
It seems to be the general consensus that indexof is a bit faster, but that we're talking about such low times that it really doesn't matter much.
Go for whichever solution you prefer I guess ...
Code Snippets
public static boolean containsOnce(final String s, final CharSequence substring) {
Pattern pattern = Pattern.compile(substring.toString());
Matcher matcher = pattern.matcher(s);
if(matcher.find()){
return !matcher.find();
}
return false;
}
public static void main(String[] args) throws Exception {
System.out.println(containsOnce("aba","a")); //false
System.out.println(containsOnce("abab", "ab")); //false
System.out.println(containsOnce("aba", "b")); //true
System.out.println(containsOnce("aaa", "aa")); //true
System.out.println(containsOnce("","")); //true
System.out.println(containsOnce("ab","")); //false
}Pattern pattern = Pattern.compile(substring.toString());
Matcher matcher = pattern.matcher(s);
return matcher.find() && !matcher.find();Context
StackExchange Code Review Q#161386, answer score: 3
Revisions (0)
No revisions yet.