Java Hashmap: как получить ключ из значения?

452

Если у меня есть значение "foo"и HashMap<String> ftwдля которого ftw.containsValue("foo")возвращается true, как я могу получить соответствующий ключ? Должен ли я пройти через хэш-карту? Каков наилучший способ сделать это?

Ник Хейнер
источник
72
Обратите внимание, что не существует ни одного соответствующего ключа - вполне может быть несколько ключей, сопоставляющих одно и то же значение.
CPerkins
1
@CPerkins, но для хэш-карт, таких как <strFilename, Reader> и многих других 1 к 1, это очень полезно.
Водолей Power
Если у вас есть небольшая коллекция предметов, подумайте о создании константы public static final String TIME = "time";иproperties.put(TIME, PbActivityJpa_.time);
Basheer AL-MOMANI
возможно, это может помочь вам получить данные с карты, и вы также можете выполнить некоторую обработку. frugalisminds.com/java/java-8-stream-map-examples
Санджай-Дев

Ответы:

215

Если вы решите использовать библиотеку Commons Collections вместо стандартного API Java Collections, вы сможете легко добиться этого.

Интерфейс BidiMap в библиотеке коллекций представляет собой двунаправленную карту, позволяющую сопоставить ключ со значением (например, карты нормалей), а также сопоставить значение ключу, что позволяет выполнять поиск в обоих направлениях. Получение ключа для значения поддерживается методом getKey () .

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

Обновить

Если вы хотите использовать API коллекций Java, вам необходимо обеспечить соотношение 1: 1 между ключами и значениями во время вставки значения в карту. Это легче сказать, чем сделать.

Как только вы сможете убедиться в этом, используйте метод entrySet () для получения набора записей (отображений) на карте. Как только вы получили набор, тип которого Map.Entry , выполните итерацию записей, сравнив сохраненное значение с ожидаемым, и получите соответствующий ключ .

Обновление № 2

Поддержку двунаправленных карт с обобщениями можно найти в Google Guava и переработанных библиотеках Commons-Collections (последняя не является проектом Apache). Спасибо Esko за указание на отсутствующую общую поддержку в коллекциях Apache Commons. Использование коллекций с обобщениями делает более понятным код.

Винит Рейнольдс
источник
23
... и если вам нравятся Generics и все эти современные вещи, в Google Collections есть BiMap, где вы можете получить ключ, соответствующий указанному значению, вызвав biMap.inverse (). get (value);
Эско
1
Да, Apache Commons Collections не поддерживает генерики. Тем не менее, как вы указали, есть Google Collections (я пока не использую - пока нет версии 1.0), и есть переработанные Commons-Collections с поддержкой Generics. Вы найдете это как проект Sourceforge @ sourceforge.net/projects/collections
Vineet Reynolds,
2
Коллекции Google не являются переработанной версией Commons-Collections.
вискисьерра
12
@ whiskeysierra: я не думаю, что кто-то (в настоящее время) так говорит.
Хафф
2
Apache Collections теперь поддерживает генерики commons.apache.org/proper/commons-collections/javadocs/…
kervin
603

Если структура данных имеет много-однозначное соответствие между ключами и значениями следует перебирать не записи и выбрать все подходящие ключи:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    Set<T> keys = new HashSet<T>();
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            keys.add(entry.getKey());
        }
    }
    return keys;
}

В случае отношения « один к одному» вы можете вернуть первый соответствующий ключ:

public static <T, E> T getKeyByValue(Map<T, E> map, E value) {
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            return entry.getKey();
        }
    }
    return null;
}

В Java 8:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    return map.entrySet()
              .stream()
              .filter(entry -> Objects.equals(entry.getValue(), value))
              .map(Map.Entry::getKey)
              .collect(Collectors.toSet());
}

Кроме того, для пользователей Guava, BiMap может быть полезным. Например:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);
Виталий Федоренко
источник
3
Вы можете сказать что-нибудь о спектакле? Что будет более оптимизировано? Это или BidiMap?
Tasomaniac
Я думал о том же решении, я проголосовал за него, конечно, но я сомневаюсь в его эффективности, когда речь идет о действительно больших коллекциях.
arjacsoh
3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap имеет временную сложность o(1). Если вы перебираете значения, это снижает производительность. Если вы хотите better performanceи one-oneимеете отношения, вы можете использовать another mapгдеvalue is a key
veer7
3
Я рекомендую заменить .filter(entry -> entry.getValue().equals(value))на, так как не было сделано никаких заявлений о способностях. Далее можно заменить на.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Хольгер
У меня возникают трудности с пониманием нотации <T, E> до Set <T> getKeysByValue () ... в чем смысл .... другой способ сделать это без использования этого? спасибо
ponderingdev
76
public class NewClass1 {

    public static void main(String[] args) {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Entry<Integer, String> entry : testMap.entrySet()) {
            if (entry.getValue().equals("c")) {
                System.out.println(entry.getKey());
            }
        }
    }
}

Некоторая дополнительная информация ... Может быть полезно для вас

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

То есть вы должны поддерживать два хеш-карты

1. Key to value

2. Value to key 

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

Фатх Рехман П
источник
19

Я думаю, что ваш выбор

  • Используйте реализацию карты, созданную для этого, например BiMap из коллекций Google. Обратите внимание, что для коллекции Google BiMap требуются уникальные значения, а также ключи, но она обеспечивает высокую производительность в обоих направлениях.
  • Вручную ведите две карты - одну для ключа -> значение, а другую карту для значения -> ключ
  • Итерируйте по entrySet()и, чтобы найти ключи, которые соответствуют значению. Это самый медленный метод, поскольку он требует итерации всей коллекции, в то время как два других метода этого не требуют.
Chi
источник
19

Вы можете вставить ключ, пару значений и ее инверсию в структуру карты

map.put("theKey", "theValue");
map.put("theValue", "theKey");

Использование map.get ("theValue") вернет "theKey".

Это быстрый и грязный способ создания постоянных карт, который будет работать только для нескольких избранных наборов данных:

  • Содержит только 1 к 1 парам
  • Набор значений не пересекается с набором ключей (1-> 2, 2-> 3 ломает его)
Chicowitz
источник
4
Это не совсем правильно. Это требует не только 1-1, но и того, что набор значений не пересекается с набором ключей. Вы не можете применить это к биективной карте {1 -> 2, 2 -> 3}: 2 является и значением, и ключом.
Луис А. Флорит
15

Украсьте карту своей собственной реализацией

class MyMap<K,V> extends HashMap<K, V>{

    Map<V,K> reverseMap = new HashMap<V,K>();

    @Override
    public V put(K key, V value) {
        // TODO Auto-generated method stub
        reverseMap.put(value, key);
        return super.put(key, value);
    }

    public K getKey(V value){
        return reverseMap.get(value);
    }
}
абхи
источник
Я думаю, что это интересный подход, хотя, поскольку отношение должно быть 1: 1, я бы полностью избавился от HashMap и вместо этого реализовал бы интерфейс Map <K, V>, чтобы избежать дублирования как значений, так и ключей.
Фран Марзоа
11

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

рекурсивный
источник
11

Чтобы найти все ключи, которые соответствуют этому значению, выполните итерацию по всем парам в hashmap, используя map.entrySet().

wsorenson
источник
4
Это решение ужасно интенсивно до такой степени, что оно нецелесообразно для больших HashMaps.
Joehot200
10

Используя Java 8:

ftw.forEach((key, value) -> {
    if (value.equals("foo")) {
        System.out.print(key);
    }
});
Фани
источник
6
value=="foo" так не пойдет. equalsследует использовать для сравнения строк.
Антон Баланюк
@Антон, правда, если valueне был интернирован.
frododot
9

Если вы строите карту в своем собственном коде, попробуйте соединить ключ и значение на карте:

public class KeyValue {
    public Object key;
    public Object value;
    public KeyValue(Object key, Object value) { ... }
}

map.put(key, new KeyValue(key, value));

Затем, когда у вас есть значение, у вас также есть ключ.

Дэвид Тинкер
источник
3
Умно, но что, если есть 2 или более объектов KeyValue, содержащих одинаковое значение? Какой ключ выбрать?
Вине Рейнольдс
2
@ Vineet, я не понимаю, как этот подход решает вопрос ОП. что вы имели в виду под «тогда, когда у вас есть значение, у вас также есть ключ»?
Цян Ли
9

Я думаю, что это лучшее решение, оригинальный адрес: Java2s

    import java.util.HashMap;
    import java.util.Map;

        public class Main {

          public static void main(String[] argv) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("1","one");
            map.put("2","two");
            map.put("3","three");
            map.put("4","four");

            System.out.println(getKeyFromValue(map,"three"));
          }


// hm is the map you are trying to get value from it
          public static Object getKeyFromValue(Map hm, Object value) {
            for (Object o : hm.keySet()) {
              if (hm.get(o).equals(value)) {
                return o;
              }
            }
            return null;
          }
        }

Простое использование: если вы поместили все данные в hasMap и у вас есть item = "Automobile", значит, вы ищете его ключ в hashMap. это хорошее решение.

getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
мальчик
источник
7

Боюсь, вам просто придется повторить свою карту. Самое короткое, что я мог придумать:

Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry<String,String> entry = iter.next();
    if (entry.getValue().equals(value_you_look_for)) {
        String key_you_look_for = entry.getKey();
    }
}
Андре ван Толи
источник
6
for(int key: hm.keySet()) {
    if(hm.get(key).equals(value)) {
        System.out.println(key); 
    }
}
user309309
источник
6

Похоже, лучший способ для вас - перебирать записи, используя, map.entrySet()так как, map.containsValue()вероятно, делает это в любом случае.

Джонас К
источник
Да, это именно то, что он делает. Но, конечно, он возвращает true, как только находит одно значение, для которого .equals - true, в отличие от того, что OP, вероятно, потребуется сделать.
CPerkins
1
Ну, итерации по записям могут возвращаться с ключом, как только он находит соответствующее значение. Множественные матчи, похоже, не были проблемой.
Джонас К
6

Для API таргетинга разработки Android <19 Виталий Федоренко решение «один к одному» не работает, потому что Objects.equalsне реализовано. Вот простая альтернатива:

public <K, V> K getKeyByValue(Map<K, V> map, V value) {
    for (Map.Entry<K, V> entry : map.entrySet()) {
            if (value.equals(entry.getValue())) {
            return entry.getKey();
        }
    }
    return null;
}
Берга
источник
Это решение работает для меня; также разрабатывается для археологической версии Android, в моем случае, чтобы получить ключ маркера Google Map, хранящегося на карте, в событии onMarkerClick. Итерация entrySet работает; но перебирать ключи и сопоставлять их с записями с помощью get () и сравнивать вывод не удалось.
Тоби Уилсон
3

Вы можете использовать ниже:

public class HashmapKeyExist {
    public static void main(String[] args) {
        HashMap<String, String> hmap = new HashMap<String, String>();
        hmap.put("1", "Bala");
        hmap.put("2", "Test");

        Boolean cantain = hmap.containsValue("Bala");
        if(hmap.containsKey("2") && hmap.containsValue("Test"))
        {
            System.out.println("Yes");
        }
        if(cantain == true)
        {
            System.out.println("Yes"); 
        }

        Set setkeys = hmap.keySet();
        Iterator it = setkeys.iterator();

        while(it.hasNext())
        {
            String key = (String) it.next();
            if (hmap.get(key).equals("Bala"))
            {
                System.out.println(key);
            }
        }
    }
}
Баласубраманец ганапати
источник
Приятно, что вы хотите предоставить полезную информацию, но это не должен быть ответ «только код», а сам код не должен быть полон запахов кода.
Том
2

Да, вам нужно пройтись по хэш-карте, если вы не реализуете что-то вроде того, что предлагают эти различные ответы. Вместо того, чтобы возиться с entrySet, я просто получил бы keySet (), перебрал бы этот набор и сохранил (первый) ключ, который возвращает вам ваше подходящее значение. Если вам нужны все ключи, которые соответствуют этому значению, очевидно, вы должны сделать все это.

Как предполагает Джонас, это может уже быть тем, что делает метод containsValue, так что вы можете просто пропустить этот тест все вместе и просто выполнять итерацию каждый раз (или, возможно, компилятор уже устранит избыточность, кто знает).

Кроме того, относительно других ответов, если ваша обратная карта выглядит так

Map<Value, Set<Key>>

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

деревенщина
источник
2

Вы можете получить ключ, используя значения, используя следующий код:

ArrayList valuesList = new ArrayList();
Set keySet = initalMap.keySet();
ArrayList keyList = new ArrayList(keySet);

for(int i = 0 ; i < keyList.size() ; i++ ) {
    valuesList.add(initalMap.get(keyList.get(i)));
}

Collections.sort(valuesList);
Map finalMap = new TreeMap();
for(int i = 0 ; i < valuesList.size() ; i++ ) {
    String value = (String) valuesList.get(i);

    for( int j = 0 ; j < keyList.size() ; j++ ) {
        if(initalMap.get(keyList.get(j)).equals(value)) {
            finalMap.put(keyList.get(j),value);
        }   
    }
}
System.out.println("fianl map ---------------------->  " + finalMap);
Amit
источник
2
public static class SmartHashMap <T1 extends Object, T2 extends Object> {
    public HashMap<T1, T2> keyValue;
    public HashMap<T2, T1> valueKey;

    public SmartHashMap(){
        this.keyValue = new HashMap<T1, T2>();
        this.valueKey = new HashMap<T2, T1>();
    }

    public void add(T1 key, T2 value){
        this.keyValue.put(key, value);
        this.valueKey.put(value, key);
    }

    public T2 getValue(T1 key){
        return this.keyValue.get(key);
    }

    public T1 getKey(T2 value){
        return this.valueKey.get(value);
    }

}
Маргус
источник
Я думаю, что этот ответ можно улучшить, добавив объяснение.
Джонатан
2
-1. Я проверил это Stringкак ключ и значение. Когда я звоню, map.add("1", "2"); map.add("1","3");я могу позвонить map.getKey("2");и получить "1", хотя "1"это ключ для "3".
Джордо
@Jonathan идея этого класса состоит в том, чтобы сохранить еще один HashMap с обратными отображениями, чтобы в дополнение к извлечению значения из ключа вы могли извлекать ключ из значения. Классы T1 и T2 немного сбивают с толку; может буквально назвать их Key & Value вместо этого? Хотя я ожидаю получить возможность получить более одного значения или более одного ключа взамен, в зависимости от данных и того, что вы хотите. Используйте с осторожностью
Chicowitz
1
@theknightwhosaysni "1" не является ключом для "2" (больше). Это также ответ на ваш вопрос, звонок getValue("1")вернется 3.
Джордо
Извините, Джордо, я ошибся по поводу стандартного поведения Hashmap: вы правы в том, что добавление нового значения для ключа должно заменить старое значение
Chicowitz
2

В java8

map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
    .forEach(entry -> System.out.println(entry.getKey()));
user3724331
источник
2
public static String getKey(Map<String, Integer> mapref, String value) {
    String key = "";
    for (Map.Entry<String, Integer> map : mapref.entrySet()) {
        if (map.getValue().toString().equals(value)) {
            key = map.getKey();
        }
    }
    return key;
}
Удивительная Индия
источник
Map <String, Integer> map = new HashMap <String, Integer> (); map.put ("A", 1); map.put ("B", 2); map.put ("C", 3); map.put ("D", 4); // System.out.println (map); System.out.println (getKey (map, "4"));
Удивительная Индия
1
Что произойдет, если несколько ключей имеют одинаковое значение?
Cà phê đen
Когда вы передадите несколько ключей, имеющих одинаковое значение, мы получим последний ключ как результат. пример: выходные данные A 1, B 1, C 1, D 2: если мы передадим значение 1, выходной результат будет C
Amazing India
@AmazingIndia Это не гарантируется и полностью зависит от конкретной реализации карты. Например, HashMap не гарантирует порядок, поэтому вы не знаете, какой вывод будет возвращен здесь.
Нильс
1
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class ValueKeysMap<K, V> extends HashMap <K,V>{
    HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>();

    @Override
    public boolean containsValue(Object value) {
        return ValueKeysMap.containsKey(value);
    }

    @Override
    public V put(K key, V value) {
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            keys.add(key);
        } else {
            Set<K> keys = new HashSet<K>();
            keys.add(key);
            ValueKeysMap.put(value, keys);
        }
        return super.put(key, value);
    }

    @Override
    public V remove(Object key) {
        V value = super.remove(key);
        Set<K> keys = ValueKeysMap.get(value);
        keys.remove(key);
        if(keys.size() == 0) {
           ValueKeysMap.remove(value);
        }
        return value;
    }

    public Set<K> getKeys4ThisValue(V value){
        Set<K> keys = ValueKeysMap.get(value);
        return keys;
    }

    public boolean valueContainsThisKey(K key, V value){
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            return keys.contains(key);
        }
        return false;
    }

    /*
     * Take care of argument constructor and other api's like putAll
     */
}
Канагавелу Сугамар
источник
1
/**
 * This method gets the Key for the given Value
 * @param paramName
 * @return
 */
private String getKeyForValueFromMap(String paramName) {
    String keyForValue = null;
    if(paramName!=null)) {
        Set<Entry<String,String>> entrySet = myMap().entrySet();
        if(entrySet!=null && entrySet.size>0) {
            for(Entry<String,String> entry : entrySet) {
                if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) {
                    keyForValue = entry.getKey();
                }
            }
        }
    }
    return keyForValue;
}
kanaparthikiran
источник
1
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class M{
public static void main(String[] args) {

        HashMap<String, List<String>> resultHashMap = new HashMap<String, List<String>>();

        Set<String> newKeyList = resultHashMap.keySet();


        for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) {
            String hashKey = (String) iterator.next();

            if (!newKeyList.contains(originalHashMap.get(hashKey))) {
                List<String> loArrayList = new ArrayList<String>();
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            } else {
                List<String> loArrayList = resultHashMap.get(originalHashMap
                        .get(hashKey));
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            }
        }

        System.out.println("Original HashMap : " + originalHashMap);
        System.out.println("Result HashMap : " + resultHashMap);
    }
}
Мадхава
источник
1

Используйте тонкую обертку: HMap

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HMap<K, V> {

   private final Map<K, Map<K, V>> map;

   public HMap() {
      map = new HashMap<K, Map<K, V>>();
   }

   public HMap(final int initialCapacity) {
      map = new HashMap<K, Map<K, V>>(initialCapacity);
   }

   public boolean containsKey(final Object key) {
      return map.containsKey(key);
   }

   public V get(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }

   public K getKey(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.keySet().iterator().next();
      return null;
   }

   public V put(final K key, final V value) {
      final Map<K, V> entry = map
            .put(key, Collections.singletonMap(key, value));
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }
}
Jayen
источник
1

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

String[] keys =  yourMap.keySet().toArray(new String[0]);

for(int i = 0 ; i < keys.length ; i++){
    //This is your key    
    String key = keys[i];

    //This is your value
    yourMap.get(key)            
}
Ману Бхат
источник
И почему кто-то должен использовать этот подход? Как вы уже сказали, производительность будет хуже, чем в других подходах.
Том
1

Я думаю, что keySet () может быть хорошо для нахождения ключей, соответствующих значению, и имеет лучший стиль кодирования, чем entrySet () .

Пример:

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

Вы можете написать код ниже:

    for (int key : map.keySet()) {
        if (map.get(key) == value) {
            res.add(key);
        }
    }

вместо того, чтобы использовать entrySet () ниже:

    for (Map.Entry s : map.entrySet()) {
        if ((int)s.getValue() == value) {
            res.add((int)s.getKey());
        }
    }

Надеюсь, поможет :)

FrancisGeek
источник
map.get(key) == valueне очень хорошая идея при проверке равенства объектов, так как вы сравниваете ссылки. Объект равенства всегда должен использовать их.equals()
frododot
1

Хотя это не дает прямого ответа на вопрос, оно связано.

Таким образом, вам не нужно продолжать создавать / повторять. Просто создайте обратную карту один раз и получите то, что вам нужно.

/**
 * Both key and value types must define equals() and hashCode() for this to work.
 * This takes into account that all keys are unique but all values may not be.
 *
 * @param map
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<V, List<K>> reverseMap(Map<K,V> map) {
    if(map == null) return null;

    Map<V, List<K>> reverseMap = new ArrayMap<>();

    for(Map.Entry<K,V> entry : map.entrySet()) {
        appendValueToMapList(reverseMap, entry.getValue(), entry.getKey());
    }

    return reverseMap;
}


/**
 * Takes into account that the list may already have values.
 * 
 * @param map
 * @param key
 * @param value
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> appendValueToMapList(Map<K, List<V>> map, K key, V value) {
    if(map == null || key == null || value == null) return map;

    List<V> list = map.get(key);

    if(list == null) {
        List<V> newList = new ArrayList<>();
        newList.add(value);
        map.put(key, newList);
    }
    else {
        list.add(value);
    }

    return map;
}
Markymark
источник
0

Важно отметить, что после этого вопроса Apache Collections поддерживает общие двунаправленные карты . Таким образом, некоторые из наиболее популярных ответов больше не являются точными в этом вопросе.

Для Serialized BidiMap, который также поддерживает повторяющиеся значения (сценарий 1-ко-многим), также рассмотрите MapDB.org .

Kervin
источник
0
  1. Если вы хотите получить ключ по значению, лучше всего использовать двунаправленную карту (двунаправленные карты), вы можете получить ключ по значению за O (1) раз.

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

  2. В Java есть структура данных, которая называется Table , которая представляет собой не что иное, как карту

    Таблица <A, B, C> == карта <A, карта <B, C>>

    Здесь вы можете получить map<B,C>, запросив T.row(a);, и вы также можете получить map<A,C>, запросивT.column(b);

В вашем особом случае вставьте C как некоторую константу.

Итак, это как <a1, b1, 1> <a2, b2, 1>, ...

Так что, если вы найдете через T.row (a1) ---> возвращает карту -> получить набор ключей, эта возвращенная карта.

Если вам нужно найти значение ключа, T.column (b2) -> возвращает карту -> получить набор ключей возвращенной карты.

Преимущества перед предыдущим случаем:

  1. Можно использовать несколько значений.
  2. Более эффективно при использовании больших наборов данных.
Бэтмен
источник