user569125
user569125

Reputation: 1463

Efficient way to delete values from hashmap object

I have HashMap object contains a key x-y-z with corresponding value test-test1-test2.

Map<String,String> map = new HashMap<String,String>(); 
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3"); 

Now I have an input string array that contains some piece of the key:

String[] rem={"x","x1"}

Based on this string array I want to remove HashMap values.

Can anyone give an efficient approach to do this operation?

Upvotes: 2

Views: 14307

Answers (4)

Tomas Lukac
Tomas Lukac

Reputation: 2225

You can do the following:

Map<String,String> map = new HashMap<String,String>(); 
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3"); 

String[] rem={"x","x1"};

for (String s : rem) {
    map.keySet().removeIf(key -> key.contains(s));
}

This piece of code will remove all entries with "x" or "x1" in the map key.

Upvotes: 0

Maria Ioannidou
Maria Ioannidou

Reputation: 1564

List remList = Arrays.asList(rem);
for (Iterator it = map.keySet().iterator(); it.hasNext();) {
    String key = (String) it.next();
    String[] tokens = key.split("-");
    for (int i = 0; i < tokens.length; i++) {
        String token = tokens[i];
        if (remList.contains(token)) {
            it.remove();
            break;
        }
     }
}

And an updated version with adding functionality based on your latest comment on this answer:

private static Map getMapWithDeletions(Map map, String[] rem) {
    Map pairs = new HashMap();
    for (int i = 0; i < rem.length; i++) {
        String keyValue = rem[i];
        String[] pair = keyValue.split("@", 2);
        if (pair.length == 2) {
            pairs.put(pair[0], pair[1]);
        }
    }
    Set remList = pairs.keySet();
    for (Iterator it = map.keySet().iterator(); it.hasNext();) {
        String key = (String) it.next();
        String[] tokens = key.split("-");
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i];
            if (remList.contains(token)) {
                it.remove();
                pairs.remove(token);
                break;
            }
        }
    }
    map.putAll(pairs);
    return map;
}

Upvotes: 5

Cowan
Cowan

Reputation: 37543

Assuming I understand you correctly, and you want to remove everything starting with 'x-' and 'x1-' from the map (but not 'x1111-', even though 'x1' is a prefix of 'x1111'), and efficiency is important, you might want to look at one of the implementations of NavigableMap, such as (for example) TreeMap.

NavigableMaps keep their entries in order (by natural key order, by default), and can be iterated over and searched very efficiently.

They also provide methods like subMap, which can produce another Map which contains those keys in a specified range. Importantly, this returned Map is a live view, which means operations on this map affect the original map too.

So:

NavigableMap<String,String> map = new TreeMap<String,String>(); 
// populate data
for (String prefixToDelete : rem) {
    // e.g. prefixToDelete = "x"
    String startOfRange = prefixToDelete + "-"; // e.g. x-
    String endOfRange = prefixToDelete + "`"; // e.g. x`; ` comes after - in sort order
    map.subMap(startOfRange, endOfRange).clear(); // MAGIC!
}

Assuming your map is large, .subMap() should be much faster than iterating over each Map entry (as a TreeMap uses a red-black tree for fast searching).

Upvotes: 0

jzd
jzd

Reputation: 23629

Edited based on edited question.

Loop through the keySet of the hashmap. When you find a key that starts with x you are looking for remove it from the map.

Something like:

for(String[] key: map.keySet()){
   if(key.length>0 && x.equals(key[0])){
      map.remove(key);
    }
}

Upvotes: 2

Related Questions