tjkmr
tjkmr

Reputation: 71

How Trim String keys in Hashmap

My app will receive a Hashmap<String,Object> from another application.

Is there any way to trim the string keys without iterating the hashmap which leads to performance downgrade becoz Hashmap may contain a lot of real data entries.

Thanks

Upvotes: 2

Views: 8550

Answers (3)

icza
icza

Reputation: 418317

One thing to note beforehand:

The map might contain 2 keys where the first is the trimmed version of the second. By doing what you want, it would overwrite/remove one of them from the map! E.g. the map might contain the keys "a " and "a", and by trimming the keys one of them will disappear!


HashMap does not provide any way to manipulate keys without iterating over them.

You can either "copy" the entries to a new map with keys trimmed (as with @RuchiraGayanRanaweera's solution), or you can do it in the same map like this:

Solution #1: Duplicate entry set and replace the different keys

So what you may do is iterate over the entries, and trim the keys. This also means that if the trimmed key is not equal to the original, you have to remove the entry with the old key and put it again with the new one. You only need to replace the entry if the trimmed version is different:

Map<String, Object> map = new HashMap<>();
for (Entry<String, Object> entry : new HashSet<>(map.entrySet())) {
    String trimmed = entry.getKey().trim();
    if (!trimmed.equals(entry.getKey())) {
        map.remove(entry.getKey());
        map.put(trimmed, entry.getValue());
    }
}

Note that it is necessary to create a new Set of the entry set because quoting from the javadoc of HashMap.entrySet():

If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined.

Solution #2: Collect first then replace the different keys

Another option is to collect the keys where the trimmed key is different, and change only those after the first iteration. This solution has the advantage of not having to "duplicate" the entry set to iterate over it. If there are relatively few keys whose trimmed variant is different, probably this is the fastest solution:

Map<String, Object> map = new HashMap<>();
// Set to store the modified keys,
// Also store the trimmed String for performance reasons 
Set<String[]> modifiedSet = new HashSet<>();
for (Entry<String, Object> entry : map.entrySet()) {
    String trimmed = entry.getKey().trim();
    if (!trimmed.equals(entry.getKey()))
        modifiedSet.add(new String[]{entry.getKey(), trimmed});
}

// Changing a key can be done in one step:
// Removing the old entry (which returns the old value) and put the new   
for (String[] modified : modifiedSet)
    map.put(modified[1], map.remove(modified[0]));

Upvotes: 1

Ruchira Gayan Ranaweera
Ruchira Gayan Ranaweera

Reputation: 35577

If there is no way to trim() keys before adding to HashMap then you have to do something like following:

HashMap<String,Object> map=new HashMap<>();
HashMap<String,Object> newMap=new HashMap<>();
for(Map.Entry<String,Object> entry:map.entrySet()){
    newMap.put(entry.getKey().trim(),entry.getValue());
}

Upvotes: 1

Beri
Beri

Reputation: 11620

You have two options:

  • trim before adding
  • iterate through MapEntries ad update all keys

In your example you have no choice, and you need to iterate over those keys.

Althought in java 8 you could use pararell streams to boost up such operation. But I would not recommend it in multithread enviroment.

Upvotes: 2

Related Questions