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

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



답변

표준 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에게 감사합니다. 제네릭과 함께 컬렉션을 사용하면 유지 관리하기 쉬운 코드가 만들어집니다.


답변

데이터 구조 에 키와 값 사이의 다 대일 매핑이있는 경우 항목을 반복하고 적합한 키를 모두 선택해야합니다.

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


답변

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 

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


답변

당신의 선택은

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

답변

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

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

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

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

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

답변

자신의 구현으로 맵을 장식하십시오.

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


답변

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