I have a HashMap and now i need to find all the keys inside the HashMap which has a particular letter inside it and replace it with another letter
So you want to change the Key. If the Hashalgorithm isn't something strange you'll have to get all key-value pairs, delete them from the hashmap, change them and reinsert them. Or insert them in a new Hashmap.
You could try this :
public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) {
Map<String, Object> tempMap = new HashMap<String, Object>();
for (Map.Entry<String, ?> entry : map.entrySet()) {
String key = entry.getKey();
if(key != null){
key = key.replace(originalChar, newChar);
}
tempMap.put(key, entry.getValue());
}
map.clear();
map.putAll(tempMap);
}
This way you handle only char, and you don't change the implementation. Plus when you iterate you don't add item in your map (it would be a bad idea).
If you don't care about the implementation simply return the tempMap and remove the clear
/putAll
part (it will consume less resources).
EDIT :
After @locka's answer I think I should specify that this method can't handle collisions.
If your Map contains the keys "toto" and "tata" and you do a `replaceKeysChar('a','o', map) only one of the values between "toto"'s value and "tata"'s value will be in the map, the other will simply be ignored.
EDIT bis:
To handle collisions with exceptions (à la @Stephen C) just replace the old for
by this one :
for (Map.Entry<String, ?> entry : map.entrySet()) {
String key = entry.getKey();
if(key != null){
key = key.replace(originalChar, newChar);
}
if(tempMap.containsKey(key))
throw new CollisionException();
tempMap.put(key, entry.getValue());
}
- Construct a new hashmap
- Copy all the (key,value) pairs from the old hashmap, except that you replace OLDCHAR with NEWCHAR in the keys
- Swap the hashmaps over.
I think people are concerned that you can't change a String key in situ because of immutability and the String's hashcode being tied the value of the string. Adding / removing keys could potentially work but then you run the risk of collisions, where you end up replacing an existing string by accident.
The most obvious way to solve this issue is to use a custom key, e.g.
public class MyKey {
static private Random r = new Random();
private String keyValue;
private final int hashCode = r.nextInt();
@Override
public int hashCode() {
return hashCode;
}
public void setKeyValue(String keyValue) {
this.keyValue = keyValue;
}
public String getKeyValue() {
return keyValue;
}
}
This key has a string key value which you can easily set / get and a hashCode which is just a random number. Once you add this key to the hash map you can change the string in situ without adding or removing the key. All you need do is iterate the key set and perform any processing you like on the key, all without affecting the hashcode or running the risk of collisions or anything else.
Here's a solution that "deals with" collisions by throwing an exception.
public void replaceKeysChar(char originalChar, char newChar, Map<String, ?> map) {
Map<String, Object> tempMap = new HashMap<String, Object>();
Set<String> tempSet = new HashSet<String>();
for (Map.Entry<String, ?> entry : map.entrySet()) {
String originalKey = entry.getKey();
String newKey = originalKey .replace(originalChar, newChar);
if (!newKey.equals(originalKey)) {
if (map.containsKey(newKey) || tempMap.containsKey(newKey)) {
throw new CollisionException(newKey);
}
tempMap.put(newKey, entry.getValue());
tempSet.add(originalKey());
}
}
map.keySet().removeAll(tempSet);
map.putAll(tempMap);
}
EDIT
Fixed bugs ... in previous versions.