Bidirectional mapping in Java witch rejects entries of key or value already existing
Asked Answered
D

1

1

I am looking for a data structure such as a bidirectional map that allows to map from a unique key to it's unique value and also from its value to the key.

I found this example of a BidiMap

public class IdToNames {
  public static void main(String[] args){
    BidiMap<String, Integer> map = new DualHashBidiMap<>();

    map.put("NameA", 100);
    map.put("NameB", 200);

    System.out.println(map.size()); //2 as expected
    System.out.println(map.get("NameA")); //100 as expected
    System.out.println(map.getKey(100)); //"NameA" as expected
  }
}

So far, so good. That was what I was looking for. But if one puts a new entry into the map, which contains already existing keys and or values, old entries are thrown away in order to keep the new entry while still having unique keys and unique values.

public class IdToNames {
  public static void main(String[] args){
    BidiMap<String, Integer> map = new DualHashBidiMap<>();

    map.put("NameA", 100);
    System.out.println(map.size()); //1 as expected
    map.put("NameB", 200);
    System.out.println(map.size()); //2 as expected
    map.put("NameA", 200);    // unfortunately this works without warnings
    System.out.println(map.size()); //1 which is problematic

    System.out.println(map.get("NameA")); //now 200
    System.out.println(map.getKey(100)); //null
  }
}

Is there a good way to prevent silently altering the map. I would prefer a data structure that rejects new entries which would violate uniqueness of existing keys or values. Any ideas are welcome.

Documentary answered 3/6, 2022 at 8:59 Comment(0)
G
1

Best way is to declare your own class, extend DualHashBidiMap and override put method so you can implement custom logic before calling actual put():

class MyDualHashBidiMap<K,V> extends DualHashBidiMap<K,V>{
    @Override
    public V put(K key, V value){
        if(this.exists(key, value)){
            return super.put(key, value)
        }

        return null;
    }

    public boolean exists(K key, V value){
        // impl existence condition
    }
}

You can also use anonymous classes right on instance creation:

public static void main(String[] args){
    BidiMap<String, Integer> map = new DualHashBidiMap(){
     
        @Override
        public V put(K key, V value){
            if(this.exists(key, value)){
                return super.put(key, value)
            }
    
            return null;
        }
    
        public boolean exists(K key, V value){
            // impl existence condition
        }
    }

    /// ... rest of impl
}
Godgiven answered 3/6, 2022 at 9:22 Comment(1)
Cannot use '<>' with anonymous inner classesDocumentary

© 2022 - 2024 — McMap. All rights reserved.