If you have a limited sequence of characters following one another you can use a Pattern
, .find()
on a matcher on your input and just invert the test:
// Only the alternation is needed, no need for the capture
private static final Pattern PATTERN
= Pattern.compile("012|123|234|345|456|567|678|789|890");
// ...
if (PATTERN.matcher(input).find())
// fail: illegal sequence found
But if you want to detect that code points follow one another you have to use character functions:
final CharBuffer buf = CharBuffer.wrap(input);
int maxSuccessive = 0;
int successive = 0;
char prev = buf.get();
char next;
while (buf.hasRemaining()) {
next = buf.get();
if (next - prev == 1)
successive++;
else {
maxSuccessive = Math.max(maxSuccessive, successive);
successive = 0;
}
prev = next;
}
// test maxSuccessive
Note however that this will test successive characters according to "canonical ordering", not collation. In some locales, for instance, what is immediately after a
is A
, not b
.
More generally, if you want to test for password requirements and constraint evolves, you are better off splitting things a bit. For instance, consider this:
public interface PasswordChecker
{
boolean isValid(final String passwd);
}
Implement this interface for each of your checks (for instance, length, presence/absence of certain characters, etc), and when you do check for a password, have a List
of checkers; the password is invalid if one checker returns false:
private final List<PasswordChecker> checkers = ...;
// then
for (final PasswordChecker checker: checkers)
if (!checker.isValid(passwd))
return false;
return true;
If you use Guava, you can forget about PasswordChecker
and use Predicate<String>
.