Map implementation with duplicate keys

后端 未结 18 1730
暗喜
暗喜 2020-11-22 15:23

I want to have a map with duplicate keys.

I know there are many map implementations (Eclipse shows me about 50), so I bet there must be one that allows this. I know

相关标签:
18条回答
  • 2020-11-22 15:47

    This problem can be solved with a list of map entry List<Map.Entry<K,V>>. We don't need to use neither external libraries nor new implementation of Map. A map entry can be created like this: Map.Entry<String, Integer> entry = new AbstractMap.SimpleEntry<String, Integer>("key", 1);

    0 讨论(0)
  • 2020-11-22 15:48

    just to be complete, Apache Commons Collections also has a MultiMap. The downside of course is that Apache Commons does not use Generics.

    0 讨论(0)
  • 2020-11-22 15:48

    If there are duplicate keys then a key may correspond to more than one value. The obvious solution is to map the key to a list of these values.

    For example in Python:

    map = dict()
    map["driver"] = list()
    map["driver"].append("john")
    map["driver"].append("mike")
    print map["driver"]          # It shows john and mike
    print map["driver"][0]       # It shows john
    print map["driver"][1]       # It shows mike
    
    0 讨论(0)
  • 2020-11-22 15:50
    class  DuplicateMap<K, V> 
    {
        enum MapType
        {
            Hash,LinkedHash
        }
    
        int HashCode = 0;
        Map<Key<K>,V> map = null;
    
        DuplicateMap()
        {
            map = new HashMap<Key<K>,V>();
        }
    
        DuplicateMap( MapType maptype )
        {
            if ( maptype == MapType.Hash ) {
                map = new HashMap<Key<K>,V>();
            }
            else if ( maptype == MapType.LinkedHash ) {
                map = new LinkedHashMap<Key<K>,V>();
            }
            else
                map = new HashMap<Key<K>,V>();
        }
    
        V put( K key, V value  )
        {
    
            return map.put( new Key<K>( key , HashCode++ ), value );
        }
    
        void putAll( Map<K, V> map1 )
        {
            Map<Key<K>,V> map2 = new LinkedHashMap<Key<K>,V>();
    
            for ( Entry<K, V> entry : map1.entrySet() ) {
                map2.put( new Key<K>( entry.getKey() , HashCode++ ), entry.getValue());
            }
            map.putAll(map2);
        }
    
        Set<Entry<K, V>> entrySet()
        {
            Set<Entry<K, V>> entry = new LinkedHashSet<Map.Entry<K,V>>();
            for ( final Entry<Key<K>, V> entry1 : map.entrySet() ) {
                entry.add( new Entry<K, V>(){
                    private K Key = entry1.getKey().Key();
                    private V Value = entry1.getValue();
    
                    @Override
                    public K getKey() {
                        return Key;
                    }
    
                    @Override
                    public V getValue() {
                        return Value;
                    }
    
                    @Override
                    public V setValue(V value) {
                        return null;
                    }});
            }
    
            return entry;
        }
    
        @Override
        public String toString() {
            StringBuilder builder = new  StringBuilder();
            builder.append("{");
            boolean FirstIteration = true;
            for ( Entry<K, V> entry : entrySet() ) {
                builder.append( ( (FirstIteration)? "" : "," ) + ((entry.getKey()==null) ? null :entry.getKey().toString() ) + "=" + ((entry.getValue()==null) ? null :entry.getValue().toString() )  );
                FirstIteration = false;
            }
            builder.append("}");
            return builder.toString();
        }
    
        class Key<K1>
        {
            K1 Key;
            int HashCode;
    
            public Key(K1 key, int hashCode) {
                super();
                Key = key;
                HashCode = hashCode;
            }
    
            public K1 Key() {
                return Key;
            }
    
            @Override
            public String toString() {
                return  Key.toString() ;
            }
    
            @Override
            public int hashCode() {
    
                return HashCode;
            }
        }
    
    0 讨论(0)
  • 2020-11-22 15:52

    I had a slightly different variant of this issue: It was required to associate two different values with same key. Just posting it here in case it helps others, I have introduced a HashMap as the value:

    /* @param frameTypeHash: Key -> Integer (frameID), Value -> HashMap (innerMap)
       @param innerMap: Key -> String (extIP), Value -> String
       If the key exists, retrieve the stored HashMap innerMap 
       and put the constructed key, value pair
    */
      if (frameTypeHash.containsKey(frameID)){
                //Key exists, add the key/value to innerHashMap
                HashMap innerMap = (HashMap)frameTypeHash.get(frameID);
                innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);
    
            } else {
                HashMap<String, String> innerMap = new HashMap<String, String>();
                innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);
                // This means the key doesn't exists, adding it for the first time
                frameTypeHash.put(frameID, innerMap );
            }
    }
    

    In the above code the key frameID is read from a input file's first string in each line, the value for frameTypeHash is constructed by splitting the remaining line and was stored as String object originally, over a period of time the file started having multiple lines (with different values) associated with same frameID key, so frameTypeHash was overwritten with last line as the value. I replaced the String object with another HashMap object as the value field, this helped in maintaining single key to different value mapping.

    0 讨论(0)
  • 2020-11-22 15:52

    what about such a MultiMap impl?

    public class MultiMap<K, V> extends HashMap<K, Set<V>> {
      private static final long serialVersionUID = 1L;
      private Map<K, Set<V>> innerMap = new HashMap<>();
    
      public Set<V> put(K key, V value) {
        Set<V> valuesOld = this.innerMap.get(key);
        HashSet<V> valuesNewTotal = new HashSet<>();
        if (valuesOld != null) {
          valuesNewTotal.addAll(valuesOld);
        }
        valuesNewTotal.add(value);
        this.innerMap.put(key, valuesNewTotal);
        return valuesOld;
      }
    
      public void putAll(K key, Set<V> values) {
        for (V value : values) {
          put(key, value);
        }
      }
    
      @Override
      public Set<V> put(K key, Set<V> value) {
        Set<V> valuesOld = this.innerMap.get(key);
        putAll(key, value);
        return valuesOld;
      }
    
      @Override
      public void putAll(Map<? extends K, ? extends Set<V>> mapOfValues) {
        for (Map.Entry<? extends K, ? extends Set<V>> valueEntry : mapOfValues.entrySet()) {
          K key = valueEntry.getKey();
          Set<V> value = valueEntry.getValue();
          putAll(key, value);
        }
      }
    
      @Override
      public Set<V> putIfAbsent(K key, Set<V> value) {
        Set<V> valueOld = this.innerMap.get(key);
        if (valueOld == null) {
          putAll(key, value);
        }
        return valueOld;
      }
    
      @Override
      public Set<V> get(Object key) {
        return this.innerMap.get(key);
      }
    
      @Override
      etc. etc. override all public methods size(), clear() .....
    
    }
    
    0 讨论(0)
提交回复
热议问题