Map with multiple keys

Ajinkya picture Ajinkya · Oct 4, 2013 · Viewed 22.8k times · Source

I am trying to implement a map like

Map<<key1, key2>, List<value>>

Map should contain 2 keys and corresponding value would be a list. I want to add records in same list if alteast one key value is equal For example consider following records

R1[key1, key2]
R2[key1, null/empty] - Key1 is equal
R3[null/empty, key2] - Key2 is equal
R4[key1, key2] - Key1 and Key2 both are equal.

all should be inserted in same list like

Key = <Key1,Key2> 
Value = <R1, R2, R3, R4>

I cant use Guava table or commons MulitKeyMap (dont want include whole library just for this) .

I tried to implement a class (which I can use as a key) which will have both key1 and key2 as attribute but implementing a effective hashcode which don't consider key1 and key2 seems bit (or may be a lot) tricky

public class Key {
    private int key1;
    private int key2;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        // Cant include key1 and key2 in hashcode 
       /* result = prime * result + key1;
        result = prime * result + key2;*/
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Key other = (Key) obj;
        if(key2 and other.key2 both not blank/null){ // pseudo code
        if (key2 == other.key2)
            return true;
        }
        if(key1 and other.key1 both not blank/null){ //pseudo code
        if (key1 == other.key1)
            return true;
        }
        return true;
    }

}

It will work if I use the same hashcode for all but it will impact the performance as I have thousands of records.


EDIT :
I cant use nested Maps like

Map<key1, Map< key2, List<value>>>

As some records might have only one key.

  R1[key1, key2]     - Have both keys
  R2[key1, null/empty] - Key1 is equal
  R3[null/empty, key2] - Key1 is missing and key2 is equal

Here R3 dont have key1 and hence cant be inserted in same location as R1 and R2


EDIT 2 :

I also wish to maintain the intertion order.

Answer

GordonM picture GordonM · Oct 4, 2013

Maps by definition have 1 key per value.

You could have a map of maps, or your key could be an object with 2 fields, but that's about as close as you can get.

Map of maps:

Map myMap<key, Map<otherkey, value>>

Custom object

public class MapKey {
    public Object keyFirstPart;
    public Object keySecondPart;

    // You'll need to implement equals, hashcode, etc
}

Map myyMap <MapKey, value>