180

I have a Map<String,String> with large number of key values pairs. Now I want to remove selected keys from that Map. Following code shows what I did to achieve that.

Set keySet = new HashSet(); //I added keys to keySet which I want to remove. 

Then :

Iterator entriesIterator = keySet.iterator();
while (entriesIterator.hasNext()) {
   map.remove( entriesIterator.next().toString());
} 

This is working fine. What would be the better approach?

4 Answers 4

341

Assuming your set contains the strings you want to remove, you can use the keySet method and map.keySet().removeAll(keySet);.

keySet returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.

Contrived example:

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

Set<String> set = new HashSet<> ();
set.add("a");
set.add("b");

map.keySet().removeAll(set);

System.out.println(map); //only contains "c"
Sign up to request clarification or add additional context in comments.

4 Comments

your suggestion is great. I guess removeAll(keySet) is doing what I did there
in terms of "efficiency" its probably just a for loop underneath, but in terms of cleaner code, nice win :)
Obvious once you see it - thanks! Still baffles me why Map does have removeAll, and for that matter isnt Iterable over the entrySet directly
Not working for me on Jenkins jvm
35

For the sake of completion, and since Google brings you here when you look for a way to achieve this:

map.entrySet().removeIf(entry -> /* decide what you want to remove here */ );

This does not assume you have a predefined set of keys to remove but rather assumes you have a condition on which the keys should be removed. From the question, it is unclear if these keys are added manually or based on some sort of condition. In the latter case, this might be the cleaner code.

For the former case, this (untested) code might work as well:

map.entrySet().removeIf(entry -> keySet.contains(entry.getKey()) );

But obviously the answer provided by @assylias is much cleaner in this case!

Comments

12

Just for the sake of completeness:

As guessed java.util.AbstractSet#removeAll really iterates over all entries, but with one little trick: It uses the iterator of the smaller collection:

if (size() <= collection.size()) {
    Iterator<?> it = iterator();
    while (it.hasNext()) {
        if (collection.contains(it.next())) {
            it.remove();
        }
    }
} else {
    Iterator<?> it = collection.iterator();
    while (it.hasNext()) {
        remove(it.next());
    }
}

Comments

3

Using Java stream:

keySet.forEach(map::remove);

2 Comments

This will not solve the actual request of removing multiple selected keys, as it doesn't have select parameter.
@dildeepak, what do you mean with "select parameter"?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.