A regex in Java. Latin letters, digits, dots, and minus signs There is a user login, and the requirements are the following:


The login must start with a Latin letter.  
The login must finish with either a Latin letter or a digit.
There may also be digits, dots, and minus signs in the login.
Min. login length is 1.
Max. login length is 20.


Here is my Java code.

boolean checkLogin(String login) {
        final int maxLength = 20;
        if (login == null || login.isEmpty() || login.length() &gt; maxLength) {
            return false;
        }

        final Pattern pattern = Pattern.compile("^[a-z][a-z\\d\\.\\-]*[a-z\\d]+$", Pattern.CASE_INSENSITIVE);
        final Matcher matcher = pattern.matcher(login);
        return matcher.matches();
}


Is everything OK?
That regex does not meet the requirements of your rules... so ... No, it is not OK.

The missing aspect is that the regex requires at least two characters, but the rules say one char is OK.

Also, I don't like that the last group has the + on it. While it is accurate in the sense that the last characters can be alpha/digit, it implies that the rule is for more than just the last character.

Another problem is that you allow logins of more than 20 characters.

A more meaningful/accurate regex would be:

^[a-z]([a-z\\d\\.\\-]{0,18}[a-z\\d])?$


Which requires 1 character, and then up to 18 'broad' characters followed by a constrained alpha/digit character.

EDIT:
2 things:


Aseem has rightly pointed out that the preceding if-condition essentially makes the {0,18} limit redundant. My preference is to keep it there for clarity, but, it does create duplication of logic which may lead to bugs later (How did I miss that the lenght is checked first... hmmm). Your call as to whether you should replace the {0,18} with just {*}.
The Pattern should be made static. There is no reason to re-compile the pattern for every call to the method (Patterns are thread-safe):

private static final Pattern pattern = Pattern.compile(
        "^[a-z]([a-z\\d\\.\\-]{0,18}[a-z\\d])?$", Pattern.CASE_INSENSITIVE);

private static final int maxLength = 20;

boolean checkLogin(String login) {

    if (login == null || login.isEmpty() || login.length() &gt; maxLength) {
        return false;
    }

    return pattern.matcher(login).matches();
}