Implementacja Map z duplikatami kluczy

Chcę mieć mapę z duplikatami kluczy.

Wiem, że jest wiele implementacji map (Eclipse pokazuje mi około 50), więc założę się, że musi być taka, która na to pozwala. Wiem, że łatwo jest napisać własną mapę, która to robi, ale wolałbym użyć jakiegoś istniejącego rozwiązania.

Może coś w commons-collections lub Google-collections?

Author: Matthias Braun, 2009-06-30

16 answers

Szukasz multimap, i rzeczywiście zarówno commons-collections, jak i Guava mają do tego kilka implementacji. Multimapy pozwalają na użycie wielu kluczy, zachowując zbiór wartości dla każdego klucza, tzn. można umieścić pojedynczy obiekt na mapie, ale można pobrać kolekcję.

Jeśli możesz używać Javy 5, wolałbym Guava ' S Multimap Jak to jest generyczne-świadomi.

 76
Author: nd.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-29 10:25:11

Nie musimy polegać na zewnętrznej bibliotece Google Collections. Możesz po prostu zaimplementować następującą mapę:

Map<String, ArrayList<String>> hashMap = new HashMap<String, ArrayList>();

public static void main(String... arg) {
   // Add data with duplicate keys
   addValues("A", "a1");
   addValues("A", "a2");
   addValues("B", "b");
   // View data.
   Iterator it = hashMap.keySet().iterator();
   ArrayList tempList = null;

   while (it.hasNext()) {
      String key = it.next().toString();             
      tempList = hashMap.get(key);
      if (tempList != null) {
         for (String value: tempList) {
            System.out.println("Key : "+key+ " , Value : "+value);
         }
      }
   }
}

private void addValues(String key, String value) {
   ArrayList tempList = null;
   if (hashMap.containsKey(key)) {
      tempList = hashMap.get(key);
      if(tempList == null)
         tempList = new ArrayList();
      tempList.add(value);  
   } else {
      tempList = new ArrayList();
      tempList.add(value);               
   }
   hashMap.put(key,tempList);
}

Upewnij się, aby dostroić kod.

 29
Author: user668943,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 13:06:43
Multimap<Integer, String> multimap = ArrayListMultimap.create();

multimap.put(1, "A");
multimap.put(1, "B");
multimap.put(1, "C");
multimap.put(1, "A");

multimap.put(2, "A");
multimap.put(2, "B");
multimap.put(2, "C");

multimap.put(3, "A");

System.out.println(multimap.get(1));
System.out.println(multimap.get(2));       
System.out.println(multimap.get(3));

Wyjście To:

[A,B,C,A]
[A,B,C]
[A]

Uwaga: musimy zaimportować pliki biblioteczne.

Http://www.java2s.com/Code/Jar/g/Downloadgooglecollectionsjar.htm

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

Lub https://commons.apache.org/proper/commons-collections/download_collections.cgi

import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.map.MultiValueMap;
 23
Author: Issac Balaji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-06 15:47:42

Możesz po prostu przekazać tablicę wartości dla wartości w zwykłej Hashmapie, symulując w ten sposób zduplikowane klucze, i to do ciebie należy decyzja, jakich danych użyć.

Możesz również użyć MultiMap , chociaż sam nie podoba mi się pomysł powielania kluczy.

 17
Author: AlbertoPL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 10:43:56

Jeśli chcesz iterować listę par klucz-wartość (tak jak napisałeś w komentarzu), to lista lub tablica powinny być lepsze. Najpierw połącz swoje klucze i wartości:

public class Pair
{
   public Class1 key;
   public Class2 value;

   public Pair(Class1 key, Class2 value)
   {
      this.key = key;
      this.value = value;
   }

}

Zastąp Class1 i Class2 typami, których chcesz użyć dla kluczy i wartości.

Teraz możesz umieścić je w tablicy lub liście i iterację nad nimi:

Pair[] pairs = new Pair[10];
...
for (Pair pair : pairs)
{
   ...
}
 10
Author: Mnementh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 10:51:58
commons.apache.org

MultiValueMap class
 5
Author: Ravi Parekh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-08 11:54:24

Ten problem można rozwiązać za pomocą listy wpisów na mapie List<Map.Entry<K,V>>. Nie musimy używać ani zewnętrznych bibliotek, ani nowej implementacji Map. Wpis mapy można utworzyć w ten sposób: Map.Entry<String, Integer> entry = new AbstractMap.SimpleEntry<String, Integer>("key", 1);

 4
Author: Thach Van,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-22 22:40:53

Ucz się na moich błędach...proszę nie wdrażać tego na własną rękę. Guava multimap jest drogą do zrobienia.

Powszechnym ulepszeniem wymaganym w multimapach jest wykluczenie duplikatów par klucz-wartość.

Implementacja/zmiana tego w Twojej implementacji może być irytująca.

W Guawie jest tak proste jak:

HashMultimap<String, Integer> no_dupe_key_plus_val = HashMultimap.create();

ArrayListMultimap<String, Integer> allow_dupe_key_plus_val = ArrayListMultimap.create();
 3
Author: frostbite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 18:29:51

Miałem nieco inny wariant tego problemu: wymagane było powiązanie dwóch różnych wartości z tym samym kluczem. Po prostu publikując go tutaj, na wypadek, gdyby pomógł innym, wprowadziłem HashMap jako wartość:

/* @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 );
        }
}

W powyższym kodzie klucz frameID jest odczytywany z pierwszego łańcucha pliku wejściowego w każdej linii, wartość dla frameTypeHash jest konstruowana przez podział pozostałej linii i była pierwotnie przechowywana jako obiekt String, przez pewien okres czasu plik zaczął mieć wiele linii (z różnymi wartościami) skojarzony z tym samym kluczem frameID, więc frameTypeHash został nadpisany ostatnią linią jako wartość. Zamieniłem obiekt String na inny obiekt HashMap jako pole wartości, co pomogło w utrzymaniu pojedynczego klucza do mapowania różnych wartości.

 1
Author: Suresh Vadali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-02 12:40:59
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;
        }
    }
 1
Author: Gabrial David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-01 08:03:56

Czy mógłbyś również wyjaśnić kontekst, dla którego próbujesz zaimplementować mapę z duplikatami kluczy? Jestem pewien, że może być lepsze rozwiązanie. Mapy są przeznaczone do przechowywania unikalnych kluczy nie bez powodu. Chociaż jeśli naprawdę chcesz to zrobić; zawsze możesz rozszerzyć klasę napisz prostą niestandardową klasę map, która ma funkcję łagodzenia kolizji i umożliwi Ci zachowanie wielu wpisów z tymi samymi kluczami.

Uwaga: musisz zaimplementować funkcję łagodzenia kolizji w taki sposób, aby, kolidujące klucze są konwertowane na unikalny zestaw "zawsze". Coś prostego, jak dodanie klucza z hashcode obiektu czy coś?

 0
Author: Priyank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 10:41:32

Aby być kompletnym, Apache Commons Collections posiada również MultiMap . Minusem jest oczywiście to, że Apache Commons nie używa generyków.

 0
Author: newacct,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 19:30:25

Z bit hack można użyć HashSet z duplikatów kluczy. Ostrzeżenie: jest to w dużym stopniu zależne od implementacji HashSet.

class MultiKeyPair {
    Object key;
    Object value;

    public MultiKeyPair(Object key, Object value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public int hashCode() {
        return key.hashCode();
    }
}

class MultiKeyList extends MultiKeyPair {
    ArrayList<MultiKeyPair> list = new ArrayList<MultiKeyPair>();

    public MultiKeyList(Object key) {
        super(key, null);
    }

    @Override
    public boolean equals(Object obj) {
        list.add((MultiKeyPair) obj);
        return false;
    }
}

public static void main(String[] args) {
    HashSet<MultiKeyPair> set = new HashSet<MultiKeyPair>();
    set.add(new MultiKeyPair("A","a1"));
    set.add(new MultiKeyPair("A","a2"));
    set.add(new MultiKeyPair("B","b1"));
    set.add(new MultiKeyPair("A","a3"));

    MultiKeyList o = new MultiKeyList("A");
    set.contains(o);

    for (MultiKeyPair pair : o.list) {
        System.out.println(pair.value);
    }
}
 0
Author: Erdem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-13 13:11:43

Jeśli istnieją zduplikowane klucze, klucz może odpowiadać więcej niż jednej wartości. Oczywistym rozwiązaniem jest mapowanie klucza do listy tych wartości.

Na przykład w Pythonie:

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
Author: cyberthanasis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 18:29:07

Użyłem tego:

java.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();

 0
Author: Alex Arvanitidis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-02 16:28:33
 1, Map<String, List<String>> map = new HashMap<>();

To gadatliwe rozwiązanie ma wiele wad i jest podatne na błędy. Informatyka oznacza, że musimy utworzyć zbiór dla każdej wartości, sprawdzić, czy jego obecność przed dodaniem lub usunięciem wartości, usuń ją ręcznie, gdy nie / align = "left" /

2, org.apache.commons.collections4.MultiMap interface
3, com.google.common.collect.Multimap interface 

Java-map-duplicate-keys

 0
Author: Vicky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-29 11:27:15