Java: Composite key in hashmaps

前端 未结 9 651
太阳男子
太阳男子 2020-12-24 12:53

I would like to store a group of objects in a hashmap , where the key shall be a composite of two string values. is there a way to achieve this?

i can simply concate

相关标签:
9条回答
  • 2020-12-24 13:40

    You don't need to reinvent the wheel. Simply use the Guava's HashBasedTable<R,C,V> implementation of Table<R,C,V> interface, for your need. Here is an example

    Table<String, String, Integer> table = HashBasedTable.create();
    
    table.put("key-1", "lock-1", 50);
    table.put("lock-1", "key-1", 100);
    
    System.out.println(table.get("key-1", "lock-1")); //prints 50
    System.out.println(table.get("lock-1", "key-1")); //prints 100
    
    table.put("key-1", "lock-1", 150); //replaces 50 with 150
    

    Happy coding!

    0 讨论(0)
  • 2020-12-24 13:46

    Why not create a (say) Pair object, which contains the two strings as members, and then use this as the key ?

    e.g.

    public class Pair {
       private final String str1;
       private final String str2;
    
       // this object should be immutable to reliably perform subsequent lookups
    }
    

    Don't forget about equals() and hashCode(). See this blog entry for more on HashMaps and keys, including a background on the immutability requirements. If your key isn't immutable, then you can change its components and a subsequent lookup will fail to locate it (this is why immutable objects such as String are good candidates for a key)

    You're right that concatenation isn't ideal. For some circumstances it'll work, but it's often an unreliable and fragile solution (e.g. is AB/C a different key from A/BC ?).

    0 讨论(0)
  • 2020-12-24 13:47

    Reading about the spaguetti/cactus stack I came up with a variant which may serve for this purpose, including the possibility of mapping your keys in any order so that map.lookup("a","b") and map.lookup("b","a") returns the same element. It also works with any number of keys not just two.

    I use it as a stack for experimenting with dataflow programming but here is a quick and dirty version which works as a multi key map (it should be improved: Sets instead of arrays should be used to avoid looking up duplicated ocurrences of a key)

    public class MultiKeyMap <K,E> {
        class Mapping {
            E element;
            int numKeys;
            public Mapping(E element,int numKeys){
                this.element = element;
                this.numKeys = numKeys;
            }
        }
        class KeySlot{
            Mapping parent;
            public KeySlot(Mapping mapping) {
                parent = mapping;
            }
        }
        class KeySlotList extends LinkedList<KeySlot>{}
        class MultiMap extends HashMap<K,KeySlotList>{}
        class MappingTrackMap extends HashMap<Mapping,Integer>{}
    
        MultiMap map = new MultiMap();
    
        public void put(E element, K ...keys){
            Mapping mapping = new Mapping(element,keys.length);
            for(int i=0;i<keys.length;i++){
                KeySlot k = new KeySlot(mapping);
                KeySlotList l = map.get(keys[i]);
                if(l==null){
                    l = new KeySlotList();
                    map.put(keys[i], l);
                }
                l.add(k);
            }
        }
        public E lookup(K ...keys){
            MappingTrackMap tmp  = new MappingTrackMap();
            for(K key:keys){
                KeySlotList l = map.get(key);
                if(l==null)return null;
                for(KeySlot keySlot:l){
                    Mapping parent = keySlot.parent;
                    Integer count = tmp.get(parent);
                    if(parent.numKeys!=keys.length)continue;
                    if(count == null){
                        count = parent.numKeys-1;
                    }else{
                        count--;
                    }
                    if(count == 0){
                        return parent.element;
                    }else{
                        tmp.put(parent, count);
                    }               
                }
            }
            return null;
        }
        public static void main(String[] args) {
            MultiKeyMap<String,String> m = new MultiKeyMap<String,String>();
            m.put("brazil", "yellow", "green");
            m.put("canada", "red", "white");
            m.put("USA", "red" ,"white" ,"blue");
            m.put("argentina", "white","blue");
    
            System.out.println(m.lookup("red","white"));  // canada
            System.out.println(m.lookup("white","red"));  // canada
            System.out.println(m.lookup("white","red","blue")); // USA
        }
    }
    
    0 讨论(0)
提交回复
热议问题