Basically the idea to achieve this is to map the keys by the value itself.
So you could have an internal map which does this (here I have a set of keys instead of just 2).
Map<V, Set<K>> keySetMap = new HashMap<V, Set<K>>();
So your Map implementation could look something like this:
public class MultiKeyMap<K, V> extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = 1L;
    private Map<V, Set<K>> keySetMap = new HashMap<V, Set<K>>();
    @Override
    public V put(K key, V value) {
        V v = null;
        Set<K> keySet = keySetMap.get(value);
        if(keySet == null) {
            keySet = new LinkedHashSet<K>();
            keySetMap.put(value, keySet);
        }
        keySet.add(key);
        v = super.put(key, value);
        // update the old keys to reference the new value
        Set<K> oldKeySet =  keySetMap.get(v);
        if(oldKeySet != null) {
            for(K k : oldKeySet) {
                super.put(k, value);
            }
        }
        return v;
    }
}
This works fine for simple (immutable) Objects:
@Test
public void multiKeyMapString() {
    MultiKeyMap<String, String> m = new MultiKeyMap<String, String>();
    m.put("1", "A");
    m.put("2", "B");
    for(Entry<String, String> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    m.put("3", "A");
    System.out.println("----");
    for(Entry<String, String> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    m.put("4", "C");
    System.out.println("----");
    for(Entry<String, String> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    m.put("3", "D");
    System.out.println("----");
    for(Entry<String, String> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    System.out.println("----");
    System.out.println("values=" + m.values());
    System.out.println();
    System.out.println();
}
with the the test above, the output would look like 
K=1, V=A
K=2, V=B
----
K=1, V=A
K=2, V=B
K=3, V=A
----
K=1, V=A
K=2, V=B
K=3, V=A
K=4, V=C
----
K=1, V=D
K=2, V=B
K=3, V=D
K=4, V=C
----
values=[D, B, C]
As you see in last output, the key 1 now maps the value D because the value previously mapped by 3 was the same as the one mapped by 1 in the step before.
But it gets tricky when you want to put a list (or any mutable object) in your map, because if you change the list (add/remove an element) then the list will have another hashCode as the one used to map the previous keys:
@Test
public void multiKeyMapList() {
    List<String> l = new ArrayList<String>();
    l.add("foo");
    l.add("bar");
    MultiKeyMap<String, List<String>> m = new MultiKeyMap<String, List<String>>();
    m.put("1", l);
    m.put("2", l);
    for(Entry<String, List<String>> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    m.get("1").add("foobar");
    m.put("3", l);
    System.out.println("----");
    for(Entry<String, List<String>> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    l = new ArrayList<String>();
    l.add("bla");
    m.put("4", l);
    System.out.println("----");
    for(Entry<String, List<String>> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    m.put("3", l);
    System.out.println("----");
    for(Entry<String, List<String>> e : m.entrySet()) {
        System.out.println("K=" + e.getKey() + ", V=" + e.getValue().toString());
    }
    System.out.println("----");
    System.out.println("values=" + m.values());
}
The test above will output something like this:
K=1, V=[foo, bar]
K=2, V=[foo, bar]
----
K=1, V=[foo, bar, foobar]
K=2, V=[foo, bar, foobar]
K=3, V=[foo, bar, foobar]
----
K=1, V=[foo, bar, foobar]
K=2, V=[foo, bar, foobar]
K=3, V=[foo, bar, foobar]
K=4, V=[bla]
----
K=1, V=[foo, bar, foobar]
K=2, V=[foo, bar, foobar]
K=3, V=[bla]
K=4, V=[bla]
----
values=[[foo, bar, foobar], [bla]]
As you see the value mapped by 1 and 2 has not been updated, after only the key 3 is turned to map another value. The reason is that the hashCode resultng from [foo, bar] is different from the one of [foo, bar, foobar] which causes Map#get to not return the correct result. To get over this you need to get set of keys by comparing to the actual value.
public class MultiKeyMap<K, V> extends LinkedHashMap<K, V> {
    private static final long serialVersionUID = 1L;
    private Map<V, Set<K>> keySetMap = new HashMap<V, Set<K>>();
    @Override
    public V put(K key, V value) {
        V v = null;
        Set<K> keySet = keySetMap.get(value);
        if (keySet == null) {
            keySet = new LinkedHashSet<K>();
            keySetMap.put(value, keySet);
        }
        keySet.add(key);
        v = super.put(key, value);
        // update the old keys to reference the new value
        for (K k : getKeySetByValue(v)) {
            super.put(k, value);
        }
        return v;
    }
    @Override
    public Collection<V> values() {
        // distinct values
        return new LinkedHashSet<V>(super.values());
    }
    private Set<K> getKeySetByValue(V v) {
        Set<K> set = null;
        if (v != null) {
            for (Map.Entry<V, Set<K>> e : keySetMap.entrySet()) {
                if (v.equals(e.getKey())) {
                    set = e.getValue();
                    break;
                }
            }
        }
        return set == null ? Collections.<K> emptySet() : set;
    }
}
Now running both test again gives the following output:
For simple (immutable) Objects
K=1, V=A
K=2, V=B
----
K=1, V=A
K=2, V=B
K=3, V=A
----
K=1, V=A
K=2, V=B
K=3, V=A
K=4, V=C
----
K=1, V=D
K=2, V=B
K=3, V=D
K=4, V=C
----
values=[D, B, C]
For object that can change
K=1, V=[foo, bar]
K=2, V=[foo, bar]
----
K=1, V=[foo, bar, foobar]
K=2, V=[foo, bar, foobar]
K=3, V=[foo, bar, foobar]
----
K=1, V=[foo, bar, foobar]
K=2, V=[foo, bar, foobar]
K=3, V=[foo, bar, foobar]
K=4, V=[bla]
----
K=1, V=[bla]
K=2, V=[bla]
K=3, V=[bla]
K=4, V=[bla]
----
values=[[bla]]
I hope this helps you find a way to implement your Map. You could instead of extending an existing implementation implement the Map interface so that you can provide an implentation for all it's methods with respect to their contracts and have the implementation of your choice as a member to handle the actual mapping.