Реализация карты с использованием дубликатов ключей

Я хочу иметь карту с дублирующими ключами.

Я знаю, что есть много реализаций карт (Eclipse показывает мне около 50), поэтому, я уверен, там должен быть тот, который позволяет это. Я знаю, что легко написать свою собственную карту, которая делает это, но я предпочел бы использовать какое-то существующее решение.

Может быть, что-то в коллекциях или коллекциях google?

Вы ищете мультимап, и для обеих коллекций коллекций и Guava для этого есть несколько реализаций. Multimaps позволяют использовать несколько ключей, поддерживая набор значений для каждого ключа, т. Е. Вы можете поместить на карту один объект, но вы получите коллекцию.

Если вы можете использовать Java 5, я бы предпочел использовать Multimap от Guava, поскольку он является универсальным.

Нам не нужно зависеть от внешней библиотеки Google Collections. Вы можете просто реализовать следующую карту:

 Map> hashMap = new HashMap(); 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); } 

Не забудьте точно настроить код.

 Multimap 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)); 

Выход:

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

Примечание: нам нужно импортировать файлы библиотеки.

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

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

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

 import org.apache.commons.collections.MultiMap; import org.apache.commons.collections.map.MultiValueMap; 

Вы можете просто передать массив значений для значения в обычном HashMap, таким образом, имитируя дубликаты ключей, и вам решать, какие данные использовать.

Вы также можете использовать MultiMap , хотя мне не нравится идея дублировать ключи.

Если вы хотите перебирать список пар ключ-значение (как вы писали в комментарии), тогда список или массив должны быть лучше. Сначала объедините свои ключи и значения:

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

Замените Class1 и Class2 на типы, которые вы хотите использовать для ключей и значений.

Теперь вы можете поместить их в массив или список и перебрать их:

 Pair[] pairs = new Pair[10]; ... for (Pair pair : pairs) { ... } 
 commons.apache.org MultiValueMap class 

Эта проблема может быть решена с помощью списка элементов списка карт List> . Нам не нужно использовать ни внешние библиотеки, ни новую реализацию Map. Запись карты может быть создана следующим образом: Map.Entry entry = new AbstractMap.SimpleEntry("key", 1);

Учитесь на моих ошибках … пожалуйста, не реализуйте это самостоятельно. Гуава-мультимап – это путь.

Общее расширение, требуемое для мультиплексов, заключается в запрещении дублирования пар ключей и значений.

Реализация / изменение этого в вашей реализации может быть раздражающим.

В Гуаве это так просто:

 HashMultimap no_dupe_key_plus_val = HashMultimap.create(); ArrayListMultimap allow_dupe_key_plus_val = ArrayListMultimap.create(); 

У меня был несколько другой вариант этой проблемы: требовалось связать два разных значения с одним и тем же ключом. Просто разместив его здесь, если он помогает другим, я ввел значение HashMap в качестве значения:

 /* @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 innerMap = new HashMap(); innerMap.put(extIP, connName+":"+frameType+":"+interfaceName); // This means the key doesn't exists, adding it for the first time frameTypeHash.put(frameID, innerMap ); } } 

В приведенном выше коде ключевой идентификатор кадра считывается из первой строки входного файла в каждой строке, значение для frameTypeHash создается путем разделения оставшейся строки и первоначально было сохранено как объект String в течение периода времени, когда файл начал иметь несколько строк ( с разными значениями), связанных с одним ключом frameID, поэтому frameTypeHash был перезаписан последней строкой в ​​качестве значения. Я заменил объект String другим объектом HashMap в качестве поля значения, это помогло сохранить один ключ для различного сопоставления значений.

 class DuplicateMap { enum MapType { Hash,LinkedHash } int HashCode = 0; Map,V> map = null; DuplicateMap() { map = new HashMap,V>(); } DuplicateMap( MapType maptype ) { if ( maptype == MapType.Hash ) { map = new HashMap,V>(); } else if ( maptype == MapType.LinkedHash ) { map = new LinkedHashMap,V>(); } else map = new HashMap,V>(); } V put( K key, V value ) { return map.put( new Key( key , HashCode++ ), value ); } void putAll( Map map1 ) { Map,V> map2 = new LinkedHashMap,V>(); for ( Entry entry : map1.entrySet() ) { map2.put( new Key( entry.getKey() , HashCode++ ), entry.getValue()); } map.putAll(map2); } Set> entrySet() { Set> entry = new LinkedHashSet>(); for ( final Entry, V> entry1 : map.entrySet() ) { entry.add( new Entry(){ 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 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 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; } } 

Не могли бы вы также объяснить контекст, для которого вы пытаетесь реализовать карту с дублирующими ключами? Я уверен, что может быть лучшее решение. Карты предназначены для сохранения уникальных ключей по уважительной причине. Хотя, если вы действительно хотели это сделать; вы всегда можете расширить class, чтобы написать простой пользовательский class карты, который имеет функцию предотвращения конфликтов и позволит вам хранить несколько записей с одинаковыми ключами.

Примечание. Вы должны реализовать функцию предотвращения столкновений, так что конфликтующие ключи преобразуются в уникальный набор «всегда». Что-то простое, добавив ключ с hash-кодом объекта или что-то еще?

просто чтобы быть полным, коллекции Apache Commons также имеют MultiMap . Конечно, недостатком является то, что Apache Commons не использует Generics.

С небольшим взломом вы можете использовать HashSet с дублирующимися ключами. ПРЕДУПРЕЖДЕНИЕ: это сильно зависит от реализации 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 list = new ArrayList(); 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 set = new HashSet(); 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); } } 

Если есть дубликаты ключей, ключ может соответствовать более чем одному значению. Очевидным решением является сопоставление ключа со списком этих значений.

Например, в 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 

Я использовал это:

java.util.List> pairList= new java.util.ArrayList<>();

  1, Map> map = new HashMap<>(); 

это подробное решение имеет несколько недостатков и подвержено ошибкам. Это означает, что нам нужно создать экземпляр Collection для каждого значения, проверить его присутствие перед добавлением или удалением значения, удалить его вручную, когда значения не оставлены и т. Д.

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

Java-карту-дубликат-ключей

  • Как удалить дубликаты из списка при сохранении порядка?
  • Удалить дубликаты, сохраняющие запись с наибольшей абсолютной величиной
  • Удаление дублированных строк
  • Самый быстрый способ удаления дубликатов документов в mongodb
  • Давайте будем гением компьютера.