14

I have a List of Strings and a Map. Every key in the map needs to present in the list else I need to throw an exception. As of now I am looping the list and checking the key and throw exception if the map doesn't contains the key. Below is the sample code is what I am doing. IS there any other way in Java8 we can do it in one line or something using streams and filters ?

And also the contents in the list and keys in the map should match. That I am already handling in the separate if condition.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestClass {

    public static void main(String[] args) {

        List<String> ll = new ArrayList<>();
        Map<String, Integer> m = new HashMap<>();
        ll.add("a");
        ll.add("b");
        ll.add("d");

        m.put("a", 1);
        m.put("b", 1);
        m.put("c", 1);

        if(ll.size() != m.size){
       System.out.println("Throw Exception");
         }

        for(String s : ll) {

            if(!m.containsKey(s)) {
                System.out.println("Throw Exception");
            }
        }
    }
}
5
  • 2
    You are saying different things in your question and in your code. In your question you said you want to check if every key is in the list, but in the code, you are checking if everything in the list is present in the map. Commented Jan 11, 2019 at 7:02
  • How about this ll.stream().filter(s -> !m.containsKey(s)).forEach(s -> { throw new RuntimeException("Not found"); }); ? Commented Jan 11, 2019 at 7:06
  • @Sweeper Sorry , I will modify the question. Technically, the contents in the list and keys in the map should match. Commented Jan 11, 2019 at 7:10
  • 2
    If they really need to match, then test something like m.keySet().equals(new HashSet<>(ll)). Or maybe keep the required keys in a set in the first place. Commented Jan 11, 2019 at 7:39
  • 1
    @sparker Seems like what you are expecting your code does is not what it actually is doing. Maybe think about it and rephrase the question to clear out the doubt. Commented Jan 11, 2019 at 7:52

6 Answers 6

9

Every key in the map needs to present in the list else I need to throw an exception

You could do it using Stream.anyMatch and iterating on the keyset of the map instead as (variable names updated for readability purpose) :

if(map.keySet().stream().anyMatch(key -> !list.contains(key))) {
    throw new CustomException("");
}

Better and as simple as it gets, use List.containsAll :

if(!list.containsAll(map.keySet())) {
    throw new CustomException("");
} 

Important: If you can trade for O(n) space to reduce the runtime complexity, you can create a HashSet out of your List and then perform the lookups. It would reduce the runtime complexity from O(n^2) to O(n) and the implementation would look like:

Set<String> allUniqueElementsInList = new HashSet<>(list);
if(!allUniqueElementsInList.containsAll(map.keySet())) {
    throw new CustomException("");
}
Sign up to request clarification or add additional context in comments.

1 Comment

Or if(! map.keySet().stream().allMatch(list::contains)), but of course, if(!list.containsAll(map.keySet())) is the canonical solution.
3

We can try adding the list to a set, then comparing that set with the keyset from your hashmap:

List<String> ll = new ArrayList<>();
ll.add("a");
ll.add("b");
ll.add("d");

Map<String, Integer> m = new HashMap<>();
m.put("a", 1);
m.put("b", 1);
m.put("c", 1);

Set<String> set = new HashSet<String>(ll);

if (Objects.equals(set, m.keySet())) {
    System.out.println("sets match");
}
else {
    System.out.println("sets do not match");
}

3 Comments

I think OP is looking for an answer wrt to java-8 (something using streams and filters) here.
@NicholasK well there is nothing in the code here, that doesn't work with java8., right? But yeah the throwing of exception is definitely missing and also an unwanted creation of Set which doesn't seem to be required for the purpose of OP.
Ummm... if (...m.keySet() == null ...) ... what is that? The keySet can never be null, and in any case: the comparison of the size() and the containsAll call boil down to a simple if (Objects.equals(m.keySet(), set)) ...
2

Simply use the following :-

m.keySet().stream().filter(e -> !ll.contains(e))
                   .findAny()
                   .ifPresent(e -> throwException("Key Not found : " + e));

And define the throwException method below :

public static void throwException(String msg) {
    throw new RuntimeException(msg);
}

Comments

1

You can simply change your existing code to -

if(!m.keySet().containsAll(ll)) {
    System.out.println("Throws Exception");
}

This will solve your problem. :)

6 Comments

This logic has a problem. Should the hashmap's keyset contain extra items, your code would still return true. Also, if null on both sides of the comparison means equal, then you would have to cover that case as well.
@p.bansal - The same check performed in reverse was what OP is mostly trying to look forward to.
@nullpointer This matches the OP’s code but not the text in the question, which requests the reverse. So +1 from me on this answer. But then the OP said in comments that the map keys must match the list, a yet again different check. (Sigh.)
@StuartMarks well, if they must match, I’d use if(m.size() != ll.size() || !m.keySet().containsAll(ll)), as I suppose, m.keySet().containsAll(ll) is potentially faster than ll.containsAll(m.keySet())
@Holger At the time this answer was written, it matched the code in the question. The OP subsequently changed the requirements.
|
1

Try this:

if ((ll == null && m == null) ||                            // if both are null
   ((ll.size() == m.size() && m.keySet().containsAll(ll)))  // or contain the same elements
) {
    System.out.println("Collections contain the same elements");
} else {
    throw new CustomException("Collections don't match!");
}

Comments

1

Here is another solution:

    if (ll  .parallelStream()
            .filter(v -> !m.containsKey(v)) // Filter alle values not contained in the map
            .count() == 0) { // If no values are left then every key was present
        // do something
    } else {
        throw new RuntimeException("hello");
    }

Just wanted to show a different approach

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.