값 "foo"
이 있고 HashMap<String> ftw
를 ftw.containsValue("foo")
반환 true
하는 경우 해당 키를 어떻게 얻을 수 있습니까? 해시 맵을 반복해야합니까? 가장 좋은 방법은 무엇입니까?
public static final String TIME = "time";
하고properties.put(TIME, PbActivityJpa_.time);
값 "foo"
이 있고 HashMap<String> ftw
를 ftw.containsValue("foo")
반환 true
하는 경우 해당 키를 어떻게 얻을 수 있습니까? 해시 맵을 반복해야합니까? 가장 좋은 방법은 무엇입니까?
public static final String TIME = "time";
하고properties.put(TIME, PbActivityJpa_.time);
답변:
표준 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);
o(1)
합니다. 값을 반복하면 성능이 저하됩니다. a를 원하고 관계 better performance
가 있다면 one-one
, 다음을 사용할 수 있습니다 another map
.value is a key
.filter(entry -> entry.getValue().equals(value))
에 대한 더 문으로 기능을하지 않았다. 또한, 당신은 대체 할 수 와.filter(entry ->
Objects.equals
(entry.getValue(), value))
null
.map(entry -> entry.getKey())
.map(Map.Entry::getKey)
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
이 경우 두 번째 해시 맵을 사용하여 키를 얻을 수 있습니다.
키, 값 쌍 및 그 역수를 모두 맵 구조에 삽입 할 수 있습니다.
map.put("theKey", "theValue");
map.put("theValue", "theKey");
map.get ( "theValue")를 사용하면 "theKey"가 반환됩니다.
상수 맵을 만든 빠르고 더러운 방법입니다. 일부 맵 세트에서만 작동합니다.
자신의 구현으로 맵을 장식하십시오.
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);
}
}
자바 8 :
ftw.forEach((key, value) -> {
if (value.equals("foo")) {
System.out.print(key);
}
});
value=="foo"
이 작동하지 않습니다. equals
문자열을 비교하는 데 사용해야합니다.
value
억류 되지 않는 한 true .
자신의 코드로지도를 작성하는 경우지도에 키와 값을 조합 해보십시오.
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object key, Object value) { ... }
}
map.put(key, new KeyValue(key, value));
그런 다음 가치가 있으면 키도 있습니다.
이것이 최선의 해결책이라고 생각합니다. 원래 주소 : 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));
for(int key: hm.keySet()) {
if(hm.get(key).equals(value)) {
System.out.println(key);
}
}
어쨌든 아마도 이것을하기 map.entrySet()
때문에 항목을 반복하는 것이 가장 좋은 방법 인 map.containsValue()
것 같습니다.
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;
}
아래를 사용할 수 있습니다 :
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);
}
}
}
}
예, 이러한 다양한 답변이 제안하는 내용을 따라 무언가를 구현하지 않는 한 해시 맵을 반복해야합니다. entrySet을 다루지 않고 keySet ()을 가져 와서 해당 세트를 반복하고 일치하는 값을 얻는 (첫 번째) 키를 유지합니다. 해당 값과 일치하는 모든 키가 필요한 경우 모든 작업을 수행해야합니다.
Jonas가 제안했듯이 이것은 이미 containsValue 메소드가 수행하는 작업 일 수 있으므로 테스트를 건너 뛰고 매번 반복을 수행 할 수 있습니다 (또는 컴파일러는 이미 중복성을 제거 할 것입니다).
또한 역방향 맵이 다음과 같은 경우 다른 답변과 관련하여
Map<Value, Set<Key>>
해당 기능이 필요한 경우 고유하지 않은 키-> 값 매핑을 처리 할 수 있습니다. 그것은 사람들이 두 개의 맵을 사용하여 여기에 제안하는 솔루션 중 하나에 잘 통합 될 것입니다.
다음 코드를 사용하여 값을 사용하여 키를 얻을 수 있습니다.
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);
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);
}
}
String
키와 값으로 테스트했습니다 . 전화 map.add("1", "2"); map.add("1","3");
를 걸면 열쇠가 되더라도 전화를 걸고 map.getKey("2");
검색 할 수 있습니다 . "1"
"1"
"3"
getValue("1")
돌아갑니다 3
.
java8에서
map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
.forEach(entry -> System.out.println(entry.getKey()));
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;
}
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
*/
}
/**
* 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;
}
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);
}
}
얇은 래퍼 사용 : 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;
}
}
내 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)
}
내가 생각하는 키 집합 () 값에 매핑하는 열쇠를 발견하고보다 더 나은 코딩 스타일이 잘 될 수있다 ) (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()
이 질문에 직접 대답하지는 않지만 관련이 있습니다.
이런 식으로 계속 생성 / 반복 할 필요가 없습니다. 리버스 맵을 한 번만 만들고 필요한 것을 얻으십시오.
/**
* 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;
}
이 질문 이후 Apache Collections는 Generic BidiMaps를 지원합니다 . 따라서 가장 많이 투표 된 답변 중 몇 가지는 더 이상 정확하지 않습니다.
중복 값을 지원하는 직렬화 된 BidiMap의 경우 (일대 다 시나리오) MapDB.org 도 고려 하십시오 .
값에서 키를 얻으려면 bidimap (양방향 맵)을 사용하는 것이 가장 좋습니다 .O (1) 시간 안에 값에서 키를 가져올 수 있습니다.
그러나 이것의 단점은 고유 한 키 세트와 값 세트 만 사용할 수 있다는 것입니다.
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)->의 맵을 반환합니다-> 반환 된 맵의 키 집합을 가져옵니다.
이전 사례에 비해 장점 :