Java Hashmap : 가치에서 키를 얻는 방법?


451

"foo"이 있고 HashMap<String> ftwftw.containsValue("foo")반환 true하는 경우 해당 키를 어떻게 얻을 수 있습니까? 해시 맵을 반복해야합니까? 가장 좋은 방법은 무엇입니까?


72
해당하는 단일 키가 없습니다. 동일한 값에 여러 키가 매핑 될 수도 있습니다.
CPerkins

1
@CPerkins이지만 <strFilename, Reader>와 같은 해시 맵 및 많은 다른 1 대 1의 경우 매우 유용합니다.
물병 자리 힘

당신이 항목의 작은 컬렉션이 경우, 상수를 만드는 것을 고려 public static final String TIME = "time";하고properties.put(TIME, PbActivityJpa_.time);
바시르 AL-MOMANI에게

아마도 이것은 맵에서 데이터를 얻는 데 도움이 될 수 있으며 일종의 처리도 수행 할 수 있습니다. frugalisminds.com/java/java-8-stream-map-examples
Sanjay-Dev

답변:


215

표준 Java Collections API 대신 Commons Collections 라이브러리 를 사용하도록 선택하면 이를 쉽게 달성 할 수 있습니다.

Collections 라이브러리 의 BidiMap 인터페이스는 양방향 맵이므로 키를 값 (예 : 일반 맵)에 맵핑하고 값을 키에 맵핑 할 수 있으므로 양방향으로 조회를 수행 할 수 있습니다. getKey () 메소드 는 값에 대한 키를 얻는 것을 지원합니다 .

그러나 bidi 맵에는 여러 값을 키에 매핑 할 수 없으므로 데이터 세트에 키와 값 사이에 1 : 1 매핑이 없으면 입찰을 사용할 수 없습니다.

최신 정보

Java Collections API를 사용하려면 값을 맵에 삽입 할 때 키와 값 사이의 1 : 1 관계를 보장해야합니다. 이것은 말보다 쉽습니다.

확인 후 entrySet () 메소드 를 사용하여 맵에서 항목 세트 (매핑)를 얻습니다. 유형이 Map.Entry 인 세트를 얻은 후에 는 저장된 값 을 예상 과 비교하여 항목을 반복 하고 해당 키를 얻습니다 .

업데이트 # 2

제네릭을 사용한 bidi 맵 지원은 Google Guava 및 리팩토링 된 Commons-Collections 라이브러리 에서 찾을 수 있습니다 (후자는 Apache 프로젝트가 아닙니다). Apache Commons Collections에서 누락 된 일반 지원을 지적한 Esko에게 감사합니다. 제네릭과 함께 컬렉션을 사용하면 유지 관리하기 쉬운 코드가 만들어집니다.


23
... 제네릭과 현대적인 모든 것을 좋아한다면 Google 컬렉션에는 BiMap.inverse (). get (value);
Esko

1
예, Apache Commons Collections는 제네릭을 지원하지 않습니다. 그러나 지적한대로 Google Collections가 있으며 (아직 1.0 릴리스는 사용하지 않음) Generics를 지원하는 리팩토링 된 Commons-Collections가 있습니다. 당신은 소스 포지 프로젝트로이를 찾을 수 @ sourceforge.net/projects/collections을
Vineet 레이놀즈

2
Google 컬렉션은 Commons-Collections의 리팩토링 된 버전 이 아닙니다 .
위스키 시에라

12
@ whiskeysierra : 나는 (현재) 그렇게 말하는 사람이 없다고 생각합니다.
허프

2
아파치 컬렉션은 이제 제네릭 지원 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;
}

자바 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());
}

또한 구아바 사용자의 경우 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)합니다. 값을 반복하면 성능이 저하됩니다. a를 원하고 관계 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)
홀거

Set <T> getKeysByValue () 전에 <T, E> 표기법을 이해하는 데 어려움이 있습니다. 요점은 무엇입니까 ... 감사합니다
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());
            }
        }
    }
}

추가 정보 ... 도움이 될 수 있습니다

해시 맵이 실제로 큰 경우 위의 방법이 좋지 않을 수 있습니다. 해시 맵에 고유 키 대 고유 값 맵핑이 포함 된 경우 값에서 키로의 맵핑을 포함하는 하나 이상의 해시 맵을 유지할 수 있습니다.

즉, 두 개의 해시 맵을 유지해야합니다

1. Key to value

2. Value to key 

이 경우 두 번째 해시 맵을 사용하여 키를 얻을 수 있습니다.


19

당신의 선택은

  • Google 컬렉션 의 BiMap 과 같이이를 위해 빌드 된 맵 구현을 사용하십시오 . Google 컬렉션 BiMap에는 키뿐만 아니라 고유 한 값이 필요하지만 양방향 성능에서 높은 성능을 제공합니다.
  • 키-> 값에 대한 맵과 값-> 키에 대한 맵을 수동으로 유지 관리
  • 및를 반복 entrySet()하여 값과 일치하는 키를 찾습니다. 이 방법은 전체 컬렉션을 반복해야하는 반면 다른 두 방법은 필요하지 않기 때문에 가장 느린 방법입니다.

19

키, 값 쌍 및 그 역수를 모두 맵 구조에 삽입 할 수 있습니다.

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

map.get ( "theValue")를 사용하면 "theKey"가 반환됩니다.

상수 맵을 만든 빠르고 더러운 방법입니다. 일부 맵 세트에서만 작동합니다.

  • 1 ~ 1 쌍만 포함
  • 값 세트가 키 세트와 분리되어 있습니다 (1-> 2, 2-> 3이 키를 분리).

4
이것은 실제로 올바르지 않습니다. 이것은 1-1을 요구할뿐만 아니라, 값 세트가 키 세트와 분리되어 있어야합니다. 이지도를 이차원지도 {1-> 2, 2-> 3}에 적용 할 수 없습니다. 2는 값이자 키입니다.
Luis A. Florit

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> 인터페이스를 구현하여 값과 키가 중복되는 것을 피하기 위해 이것이 흥미로운 접근법이라고 생각합니다.
Fran Marzoa

11

여러 키가 동일한 값에 매핑 될 수 있으므로 명확한 대답은 없습니다. 자신의 코드로 고유성을 강화하는 경우 가장 좋은 해결책은 두 개의 해시 맵을 사용하여 양방향으로 매핑을 추적하는 클래스를 만드는 것입니다.


11

해당 값에 매핑되는 모든 키를 찾으려면을 사용하여 해시 맵의 모든 쌍을 반복하십시오 map.entrySet().


4
이 솔루션은 큰 HashMap에서 비현실적인 지점까지 엄청나게 집중적입니다.
Joehot200

10

자바 8 :

ftw.forEach((key, value) -> {
    if (value.equals("foo")) {
        System.out.print(key);
    }
});

6
value=="foo" 이 작동하지 않습니다. equals문자열을 비교하는 데 사용해야합니다.
Anton Balaniuc

@Anton, value억류 되지 않는 한 true .
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
영리하지만 동일한 값을 포함하는 둘 이상의 KeyValue 객체가있는 경우 어떻게해야합니까? 어떤 키를 선택해야합니까?
Vineet Reynolds

2
@Vineet, 나는이 접근법이 OP의 질문을 어떻게 해결하는지 알지 못합니다. "그러면 가치가있을 때 열쇠도 있습니다."는 무슨 뜻입니까?
Qiang Li

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

6

어쨌든 아마도 이것을하기 map.entrySet()때문에 항목을 반복하는 것이 가장 좋은 방법 인 map.containsValue()것 같습니다.


그렇습니다. 그러나 물론 OP 가해 야 할 일과는 반대로 .equals에 해당하는 하나의 값을 찾으면 즉시 true를 반환합니다.
CPerkins 2018 년

1
글쎄, 항목을 반복하면 일치하는 값을 찾으면 즉시 키로 반환 할 수 있습니다. 여러 경기가 걱정되지 않았습니다.
Jonas K

6

API <19를 대상으로하는 Android 개발의 경우 Vitalii Fedorenko 일대일 관계 솔루션이 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;
}

이 솔루션은 저에게 효과적입니다. 제 경우에는 "onMarkerClick"이벤트에서 Map에 Google 맵 마커의 키를 가져 오기 위해 고고학 Android 버전을 개발 중입니다. entrySet를 반복하면 작동합니다. 그러나 키를 반복하고 get ()을 사용하여 항목과 일치시키고 출력을 비교하지 못했습니다.
Toby Wilson

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

유용한 정보를 제공하는 것이 좋지만 "코드 만"응답이 아니어야하며 코드 자체도 코드 냄새로 가득하지 않아야합니다.
Tom

2

예, 이러한 다양한 답변이 제안하는 내용을 따라 무언가를 구현하지 않는 한 해시 맵을 반복해야합니다. entrySet을 다루지 않고 keySet ()을 가져 와서 해당 세트를 반복하고 일치하는 값을 얻는 (첫 번째) 키를 유지합니다. 해당 값과 일치하는 모든 키가 필요한 경우 모든 작업을 수행해야합니다.

Jonas가 제안했듯이 이것은 이미 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);

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

}

설명을 추가하면이 답변을 향상시킬 수 있다고 생각합니다.
Jonathan

2
-1. String키와 값으로 테스트했습니다 . 전화 map.add("1", "2"); map.add("1","3");를 걸면 열쇠가 되더라도 전화를 걸고 map.getKey("2");검색 할 수 있습니다 . "1""1""3"
jlordo

@Jonathan이 클래스의 아이디어는 다른 HashMap을 리버스 매핑으로 유지하여 키에서 값을 검색하는 것 외에도 값에서 키를 검색하는 것입니다. T1 & T2 클래스는 약간 혼동됩니다. 문자 그대로 Key & Value로 이름을 지정합니까? 데이터 및 원하는 내용에 따라 두 개 이상의 값 또는 두 개 이상의 키를받을 수있는 기능을 기대할 수 있습니다. 주의해서 사용하십시오
Chicowitz

1
@theknightwhosaysni "1"은 "2"의 키가 아닙니다 (더 이상). 이 호출, 또한 귀하의 질문에 대한 대답은 getValue("1")돌아갑니다 3.
jlordo

죄송합니다. jlordo, 표준 Hashmap 동작에 대해 착각했습니다. 키에 새 값을 추가하면 이전 값을 대체해야합니다.
Chicowitz

2

java8에서

map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
    .forEach(entry -> System.out.println(entry.getKey()));

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 <문자열, 정수> (); 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"));
Amazing India

1
여러 키의 값이 같은 경우 어떻게됩니까?
Cà phê đen

u가 여러 키를 동일한 값으로 전달하면 마지막 키가 결과로 나타납니다. 예 : A 1, B 1, C 1, D 2 출력 : 1 값을 전달하면 출력은 C가됩니다.
Amazing India

@AmazingIndia 이것은 보장되지 않으며 특정 맵 구현에 전적으로 의존합니다. 예를 들어 HashMap은 주문을 보장하지 않으므로 어떤 출력이 여기에 반환 될지 모릅니다.
Niels Doucet

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;
}

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;
   }
}

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)            
}

그리고 왜 누군가가 그 접근법을 사용해야합니까? 이미 말했듯이 다른 접근 방식보다 성능이 떨어집니다.
Tom

1

내가 생각하는 키 집합 () 값에 매핑하는 열쇠를 발견하고보다 더 나은 코딩 스타일이 잘 될 수있다 ) (entrySet을 .

전의:

당신은 HashMap의가 있다고 가정 지도 , ArrayList를의 고해상도 하는 찾으려는 모든 키 다음에 키 저장에 매핑을, 입술을 .

아래 코드를 작성할 수 있습니다.

    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());
        }
    }

그것이 도움이되기를 바랍니다 :)


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;
}

0

이 질문 이후 Apache Collections는 Generic BidiMaps를 지원합니다 . 따라서 가장 많이 투표 된 답변 중 몇 가지는 더 이상 정확하지 않습니다.

중복 값을 지원하는 직렬화 된 BidiMap의 경우 (일대 다 시나리오) MapDB.org 도 고려 하십시오 .


0
  1. 값에서 키를 얻으려면 bidimap (양방향 맵)을 사용하는 것이 가장 좋습니다 .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. 큰 데이터 세트를 사용할 때 더 효율적입니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.