2

I have a map that stores a set of questions and answers. There cannot be questions with empty answers or answers with empty questions. Below is how I have initialized my map.

Optional<Map<String, String>> questionsAndAnswers();

I'm validating the empty strings for questions/answers in the following manner.

questionsAndAnswers().ifPresent(questionsAndAnswers -> {
        if (questionsAndAnswers.isEmpty()) {
            throw new IllegalArgumentException("questions cannot be empty if present");
        } else if (questionsAndAnswers.keySet().contains("") || questionsAndAnswers.values().contains("")) {
            throw new IllegalArgumentException("Questions or answers cannot be empty");
        }
    });

Is there a better way to achieve this? Any advice would be much appreciated.

UPDATE: There's no specific need for me to have these checks done in two separate conditions.

AnOldSoul
  • 4,017
  • 12
  • 57
  • 118
  • Is is possible for you to not store the empty questions/answers in the first place. I know I am going off tangent. I just wanted to confirm. – Yoshikage Kira May 26 '21 at 19:22
  • This is part of a library package, and I will pass the data gathered here to another API. So I want to make sure that I don't end up passing any empty questions or answers to that API :) – AnOldSoul May 26 '21 at 19:25
  • 1
    So an empty map is a problem but an empty optional, not containing a map at all, is fine? Why does this method return an optional at all? – Holger May 27 '21 at 08:52
  • This map contains questions and answers. Not passing them is fine, in which case I'll use default values. But if users decide to provide their own set of questions and answers, they shouldn't leave any question or answer empty. Hope that makes sense – AnOldSoul May 27 '21 at 14:56

4 Answers4

1

You could try below

    questionsAndAnswers().ifPresent(qna -> {
        if (qna.isEmpty() || qna.containsKey("") || qna.containsValue("")) {
            throw new IllegalArgumentException("Error Message Comes Here");
        }
    });
0

You throw two different exceptions, so there has to be a difference between an empty map and a empty Entry of the Map.

On the second if you should check, if the key or value is null or empty:

questionsAndAnswers().ifPresent(pMap -> {
            if(pMap.isEmpty())
                throw new IllegalArgumentException();
            
            if(pMap.keySet().stream().anyMatch(pKey -> pKey == null || pKey.trim().isEmpty())
                    || pMap.values().stream().anyMatch(pValue -> pValue == null || pValue.trim().isEmpty()))
                throw new IllegalArgumentException();
        });

Edit: For strings you can use Apache Commons: https://stackoverflow.com/a/14721575/11050826

ses
  • 168
  • 1
  • 11
0

questionsAndAnswers().ifPresent(ConcurrentHashMap::new); throws a NullPointerException if there is any null key/value

vincendep
  • 528
  • 4
  • 10
0

First of all: The code you showed above contains some syntax errors. Probably your IDE or compiler will help you sort that out.

Your map stores key/value pairs where either key or value is the question and the other one is the answer. What you demand is there must not exist empty keys or empty values.

You can iterate through the map and find entries with empty values. What you are going to do about them is then still up to you...

for (Map.Entry<String, String> entry: questionsAndAnswers) {
    if (entry.getValue()==null || entry.getValue().isBlank()) {
        // here do what you need to do with an emty value
        // removing that from the map may be thrilling while you loop over it
    }
}

Once that is solved, you may want to care about null or empty questions. The documentation says "An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value." That means there is at most one emtpy question. And to find it you simply do

questionsAndAnswers.get(null); // unlikely to reveal anything at all
questionsAndAnswers.get("");   // there you go, now put this answer again with the
                               // right question. 
questionsAndAnswers.remove();  // finally remove the empty question from the map
Queeg
  • 7,748
  • 1
  • 16
  • 42
  • Thanks so much for the answer. I'd like to figure out a way without using a loop and with minimal number of lines, especially any easier ways with Java 8 APIs :) – AnOldSoul May 26 '21 at 19:50