Reputation: 3390
I am across situation where I will be changing key based on value in HashMap
. My HashMap
is:
HashMap<Key, Path>
Initially I am creating Key
s for each directory Path
and putting these entries in HashMap
. When doing processing, I will take Path
based on Key
from HashMap
and process them. In some cases I will be re-calculating Key
for some Path
and want to replace old Key
with new Key
for that Path
. I want to keep unique Keys for unique Paths and update Entry in HashMap with either one. So I want to perform reverse of HashMap to update Key. What is best technique for this?
Thanks in Advance.
Upvotes: 0
Views: 3903
Reputation: 61
Needed a solution this recently, but didn't want to rely on a plugin, so I extended the base Java class. This implementation does not allow null values.
public class OneToOneMap<K,V> extends HashMap<K,V> {
public OneToOneMap() {
super();
}
public OneToOneMap(int initialCapacity) {
super(initialCapacity);
}
public OneToOneMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public OneToOneMap(Map<? extends K, ? extends V> m) {
super(m);
dedup();
}
@Override
public void putAll(Map<? extends K, ? extends V> m){
super.putAll(m);
dedup();
}
@Override
public V put(K key, V value) {
if( key == null || value == null ) return null;
removeValue(value);
return super.put(key,value);
}
public K getKey( V value ){
if( value == null || this.size() == 0 ) return null;
Set<K> keys = new HashSet<>();
keys.addAll(keySet());
for( K key : keys ){
if( value.equals(get(key) )) return key;
}
return null;
}
public boolean hasValue( V value ){
return getKey(value) != null;
}
public boolean hasKey( K key ){
return get(key) != null;
}
public void removeValue( V remove ){
V value;
Set<K> keys = new HashSet<>();
keys.addAll(keySet());
for( K key : keys ){
value = get(key);
if( value == null || key == null || value.equals(remove)) remove(key);
}
}
//can be used when a new map is assigned to clean it up
public void dedup(){
V value;
Set<V> values = new HashSet<>();
Set<K> keys = new HashSet<>();
keys.addAll(keySet());
for( K key : keys ){
value = get(key);
if( value == null || key == null || values.contains(value) ) remove(key);
else values.add(value);
}
}
}
Upvotes: 0
Reputation:
Assuming the bidirectional hash is guaranteed to be 1-to-1 and there are no concerns of memory usage, this is a pure java solution.
public class BiHash<K> extends ConcurrentHashMap<K, K> {
public void biPut(K k1, K k2)
{
super.put(k1, k2);
super.put(k2, k1);
}
}
Upvotes: 0
Reputation: 213311
May be you are looking for Google Guava's BiMap
.
A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an "inverse view", which is another bimap containing the same entries as this bimap but with reversed keys and values.
Upvotes: 5
Reputation: 24344
If you want to update a key you could do this:
String oldKey = "oldKey";
String newKey = "newKey";
map.put(newKey, map.remove(oldKey));
To get a key based on value you can either use:
For fun, here's how you could maintain two maps:
Map<String, String> keyMap = new HashMap<String, String>();
Map<String, String> valueMap = new HashMap<String, String>();
String val = "someVal";
keyMap.put("newKey", keyMap.remove(valueMap.get(val)));
valueMap.put(val, "newKey");
Upvotes: 1
Reputation: 1160
When you want to set a new key, use
hm.set(newKey, oldPath);
where hm
is your HashMap
. Then, use
hm.remove(oldKey)
to remove the old key.
Note that if you could possibly have two Path
s with the same Key
, then you'll have to reverse your HashMap
to <Path, Key>
, since one Key
would overwrite the other. To lookup a value and retrieve its key, use the entrySet()
and loop through (update 1 to the linked post).
Hope this helps!
Upvotes: 0
Reputation: 5982
I would
myHashMap.remove(Key);
then
myHashMap.put( newKey, new value);
During an iteration of the hashMap, the removal option is not allowe.
Upvotes: 0
Reputation: 70989
Add another HashMap to do the reverse mapping. Keep it in sync with the original map and that's it. I would even create a helper class that ensures all operations are synced between the two maps.
Upvotes: 3