3

I am working on a program that lets a user input an alphanumeric key, and checks if it is a valid key against some criteria, one of these is whether or not the key contains an uppercase. TThis is what I have tried so far:

else if (key.contains("QWERTYUIOPASDFGHJKLZXCVBNM")){
    UI.println("Invalid, key contains a space, illegal character");
    }

This only detects the capital letters if they are written in this order. is there a command such as key.contains i should be using?

louistcooper
  • 43
  • 1
  • 4
  • 1
    By 'the key contains an uppercase', do you mean 'the key is an uppercase letter'? Or is 'key' something other than a string containing a single character? – jarmod Mar 19 '20 at 20:18
  • 3
    The answer to such questions is pretty much always "[use a regex](https://www.vogella.com/tutorials/JavaRegularExpressions/article.html)" - they're a very helpful and powerful tool, I encourage you to learn about them in general to solve your problem – MyStackRunnethOver Mar 19 '20 at 20:21

7 Answers7

5

With streams, you can to the following.

key.chars().anyMatch(Character::isUpperCase)

This is much lighter than regexes in terms of resources.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • @KonradRudolph No, that's used by method handle. Regarding the performances, regexes can be fast if they are reused. Most of the time, people don't reuse them. Plus, the compile time is usually very slow. – Olivier Grégoire Mar 19 '20 at 21:52
  • Yeah I realised. However, don’t underestimate the heavy lifting that `char` is doing. I got bored tracing all the calls but it constructs a considerable call tree through many classes. Streams in Java are by no means lightweight. – Konrad Rudolph Mar 19 '20 at 21:58
2

Just use the proper regex with matcher.find()

Pattern.compile("[A-Z]").matcher(key).find()
m.antkowicz
  • 13,268
  • 18
  • 37
  • Will not work! You missed at least one letter: Ä! Although it is not in the list from the sample in the question, it is an Uppercase letter … like Ü, Π or Ҫ. – tquadrat Mar 19 '20 at 21:04
  • @tquadrat While I agree that the answer in itself is incomplete because of all accentuated characters, it matches exactly the list of letters expected by the questioner. – Olivier Grégoire Mar 19 '20 at 21:32
  • @OlivierGrégoire: The questioner specified, that the String may not contain any uppercase characters, but their own implementation screwed that up already as their code did not regard all possible uppercase characters. – tquadrat Mar 19 '20 at 21:38
2

Or you can do it as described by sopheamak here: How do I check if a Java String contains at least one capital letter, lowercase letter, and number?

In your example that would be:

else if (!key.equals(key.toLowerCase())

If one of the letters in key is uppercase it will not match the result of key.toLowerCase() and thus return true because of !.

Maurice
  • 6,698
  • 9
  • 47
  • 104
  • 1
    Although the regex-based solution is more generic for this class of problems, the solution here is the most pragmatic one for this specific problem. Perhaps not the fastest and not that one with the lowest memory footprint, but in these aspects at least better than the regex one. – tquadrat Mar 19 '20 at 21:00
1

You can use Apache Commons Lang (https://commons.apache.org/proper/commons-lang/). Is has a method for this:

else if (StringUtils.containsAny(key, "QWERTYUIOPASDFGHJKLZXCVBNM")){
    UI.println("Invalid, key contains a space, illegal character");
}
Daniel
  • 1,027
  • 1
  • 8
  • 23
1

You can use String#matches with the regex, .*\p{Lu}.*. Learn more about Pattern from the documentation.

Demo:

public class Main {
    public static void main(String args[]) {
        String[] keys = { "HELLO", "Hello", "hello", "hello world", "Hello World" };
        for (String key : keys) {
            if (key.matches(".*\\p{Lu}.*")) {
                System.out.println(key + " => Invalid");
            } else {
                System.out.println(key + " => Valid");
            }
        }
    }
}

Output:

HELLO => Invalid
Hello => Invalid
hello => Valid
hello world => Valid
Hello World => Invalid

Alternatively,

You can check the presence of an uppercase letter using the regex, \p{Lu}.

Demo:

import java.util.regex.Pattern;

public class Main {
    public static void main(String args[]) {
        String[] keys = { "HELLO", "Hello", "hello", "hello world", "Hello World" };
        for (String key : keys) {
            if (Pattern.compile("\\p{Lu}").matcher(key).find()) {
                System.out.println(key + " => Invalid");
            } else {
                System.out.println(key + " => Valid");
            }
        }
    }
}
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

If you use Guava, you can get it using the powerful CharMatcher:

First compile the matcher as a static member of the class so that it's done once and you don't need to recompute it at every call.

private static final CharMatcher UPPERCASE_LETTER = CharMatcher.inRange('A', 'Z');

Change it to whatever letters you actually want. For instance if you want some accentuated characters, you can extend the following:

private static final CharMatcher UPPERCASE_LETTER = CharMatcher.inRange('A', 'Z')
                                                               .or(CharMatcher.anyOf("ÁÀÄÂÉÈËÊÍÌÏÎÓÒÖÔÚÙÜÛ"));

If you're lazy and just want to delegate to Character::isUpperCase, that's also possible:

private static final CharMatcher UPPERCASE_LETTER = CharMatcher.forPredicate(Character::isUpperCase)

Then in your code, write the following:

if (UPPERCASE_LETTER.matchesAnyOf(key)) {
  // Do what you want
}
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
0

If you took the streams solution of @OlivierGrégoire and want limit it to the Capitals [A-Z] you can get it by also testing the UnicodeBlock as BASIC_LATIN. Where BASIC_LATIN is the ASCII Block of Unicode(see BASIC_LATIN )

        key.chars().anyMatch(this::isBasicLatinCapital)
        ...
        private boolean isBasicLatinCapital( int c) {
        return
            Character.UnicodeBlock.BASIC_LATIN == Character.UnicodeBlock.of(c) && Character.isUpperCase(c) ;
        }