6

I have a Collection containing some values.

Collection<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("b");
myList.add("c");

I created a Map which has some values:

Map<String, String> myMap = new HashMap<String, String>();
myMap.put("r", "r");
myMap.put("s","m");
myMap.put("t", "n");
myMap.put("a", "o");

I want to check whether the values in the list are present as a key in the map? The way which I know using Java is to iterate through the list and check if the map contains that particular value using myMap.containsKey(). I want to know if there is anything out there using streams or for-each which saves me either lines of code or an efficient way of doing that! Thanks for thinking through it.

EDIT: I want to store all the elements present in the myList which are not there in myMap. So my output can be a list e.g in this scenario [b,c].

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
Siddharth Shankar
  • 489
  • 1
  • 10
  • 21
  • 1
    `myList.forEach(x -> System.out.println(map.containsKey(x)))` but it saves you may be 2 lines of code? – Eugene May 15 '19 at 20:08
  • 1
    Why overcomplicate things? Why not simply use `myMap.keySet().containsAll(myList);`? – Pshemo May 15 '19 at 20:14
  • @Pshemo does not look like OP is after _all_ – Eugene May 15 '19 at 20:14
  • 1
    Could make a `Set` out of list and than use `retainAll` method with `keySet` parameter. Then it would be possible to know which elements of the list are keys in the map. – Michał Krzywański May 15 '19 at 20:17
  • 1
    @Eugene True, but this need to be clarified by OP. – Pshemo May 15 '19 at 20:18
  • 1
    @SiddharthShankar What is expected result here? Do you want to know if *any* element in list is used as map key, or if *all* of them are used as keys? – Pshemo May 15 '19 at 20:19
  • @Pshemo I want to check which list elements are present in the map. According to my use case, I have to store those elements which are not there in map? I will edit my question. – Siddharth Shankar May 15 '19 at 21:29
  • Do you want to modify original list, or create new one with elements which are not in map? Or maybe you just want to print them (without modifying list nor creating new one)? – Pshemo May 15 '19 at 22:15
  • The answer is going to be very subjective since the best way is in the eyes of the beholder. – WJS May 16 '19 at 00:35
  • the problem is that you have a `List` as input and `Set` as keys from the Map; so what if your List is `[a,a,b,c]` and your keySet from that Map is `[b]`, what would be the expected result? – Eugene May 16 '19 at 07:14

4 Answers4

7
Set<String> mySet = new HashSet<String>(myList);
myMap.keySet().containsAll(set);

Does this answer your question?

After your EDIT: Given the above, you can get the keys difference between two sets using the answer to one of these questions:- What is the best way get the symmetric difference between two sets in java? or Getting the difference between two sets

Anusha
  • 337
  • 2
  • 4
  • 21
  • 2
    There’s no point in copying `myList` to a `HashSet`. Just doing `myMap.keySet().containsAll(myList);` is sufficient. Unless you’re going to get the missing keys via `mySet.removeAll(myMap.keySet())`. But unless you actually do it, the `HashSet` is obsolete. – Holger May 21 '19 at 17:14
  • There is a difference in passing set and list to containsAll method here myMap.keySet().containsAll(set); As mentioned in the javadocs of containsAll method itself: _/* Returns true if this set contains all of the elements of the * specified collection. If the specified collection is also a set, this * method returns true if it is a subset of this set.**/_ – Kusum Jan 06 '20 at 06:26
3

...whether the values in the list are present as a key in the map?

As I understand this case as you need to verify whether all the elements in the myList are present as the myMap's keys. Use the Stream::allMatch method:

myMap.keySet().stream()
              .allMatch(myList::contains);

... which is the same as:

myList.keySet().containsAll(myMap);

EDIT: I want to store all the elements present in the myList which are not there in myMap. So my output can be a list e.g in this scenario [b,c].

You don't want to store all the elements in the myList since they are already there filled. You want to retain those elements using List::retainAll.

myList.retainAll(myMap.keySet());

Printing out the result of myList would produce only the keys, that have been found in the original myList and also as a key of myMap.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • 1
    I think the approach should be the opposite: myList.stream() .allMatch(myMap::containsKey) as the keys in the map do not need to be all present in the list. – Laguh May 15 '19 at 21:11
  • Yes, that's what my code does :) Note that in both cases each key from the `myMap` is checked whether exists in the `myList`. – Nikolas Charalambidis May 15 '19 at 21:31
  • By the Edit in the quesiton, OP is possibly looking for `removeIf` and not `retainAll`. – Naman May 16 '19 at 01:50
  • `myMap.keySet().stream() .allMatch(myList::contains);` is *not* the same as `myList.keySet().containsAll(myMap);` resp. `myList.stream() .allMatch(myMap::containsKey)` which @Laguh suggested. Likewise “*only the keys, that have been found*” is not the same as “*which are not there*”. For what the OP described, `removeAll` would be the right thing rather than `retainAll`. – Holger May 21 '19 at 17:20
  • @Naman or `removeAll`. The method `removeIf` is nice if you have a complex condition to check, but when it comes to mere presence in another collection, the good old bulk data methods are good enough. – Holger May 21 '19 at 17:22
1

Using Streams you can do something like:

List<String> result = myList.stream()                
                            .filter(myMap::containsKey)
                            .collect(Collectors.toList());

The resulting list will contain the values that are present as key in the map.

In case you want to print them out you can do:

result.forEach(System.out::println);
Laguh
  • 621
  • 2
  • 10
  • 23
  • You could do this a little more succinctly by using `Map.containsKey`: `myList.stream().filter(myMap::containsKey).collect(Collectors.toSet())` – xbakesx May 15 '19 at 20:59
  • @xbakesx true. I am gonna edit to include your suggestion. – Laguh May 15 '19 at 21:13
1

For: I want to store all the elements present in the myList which are not there in myMap. So my output can be a list e.g in this scenario [b,c]

Create a duplicate myList and remove all myMap's keys

        Collection<String> newList = new ArrayList<>(myList);
        newList.removeAll(myMap.keySet());
        System.out.println(newList);
Nitika Bansal
  • 740
  • 5
  • 10