Java Hashmap: kaip gauti išlaidų raktą?

Jei turiu reikšmę "foo" ir „ HashMap<String> ftw , kurių ftw.containsValue("foo") grąžina true , kaip galiu gauti atitinkamą raktą? Ar man reikia eiti per maišos žemėlapį? Koks yra geriausias būdas tai padaryti?

388
05 сент. nustatė Nick Heiner 05 Sep 2009-09-05 20:07 '09, 20:07 2009-09-05 20:07
@ 33 atsakymai
  • 1
  • 2

Jei nuspręsite rinkti kolekcijų kolekciją vietoj standartinių „Java“ API rinkinių, galite lengvai tai padaryti.

Kolekcijų bibliotekos „ BidiMap“ sąsaja yra dvikryptis žemėlapis, leidžiantis suderinti raktą su reikšme (pvz., Įprastine kortele) ir taip pat suderinti vertę su raktu, kuris leidžia ieškoti abiem kryptimis. Kaip gauti vertės raktą, gaunamas „ getKey“ () metodas.

Atsakomybės apribojimas, nors dvikalbės kortelės negali turėti daug reikšmių, susijusių su raktais, todėl, jei duomenų rinkinyje nėra 1: 1 raktų ir vertybių palyginimo, negalite naudoti bidimaps.

Atnaujinti

Jei norite pasikliauti „Java“ kolekcijų API, turėsite pateikti 1: 1 santykį tarp raktų ir reikšmių, kai įvesite vertes žemėlapyje. Tai lengviau pasakyti nei padaryta.

Kai tik galite įsitikinti, kad naudojate „ entrySet“ () metodą, norėdami gauti įrašų rinkinį (žemėlapius). Gavę rinkinį, kurio tipas yra Map.Entry , kartokite elementus, palyginkite išsaugotą vertę su tikėtinu ir gaukite atitinkamą raktą .

Atnaujinimas # 2

Parama dvikartėms kortelėms su generiniais vaistais pateikiama „ Google Guava“ ir reorganizuotose „ Commons“ kolekcijose (pastarasis nėra „Apache“ projektas). Ačiū Esko už tai, kad ji nurodė trūkstamą bendrą paramą „Apache Commons“ kolekcijose. Naudojant rinkinius su generiniais vaistais, kodas tampa patogesnis.

196
05 сент. atsakymą pateikė Vineet Reynolds 05 Sep. 2009-09-05 20:25 '09, 20:25, 2009-09-05 20:25

Jei jūsų duomenų struktūroje yra daug vertybių, atitinkančių raktus ir vertes, turėtumėte įrašyti įrašus ir pasirinkti visus reikiamus raktus:

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

Ryšio „vienas su vienu“ atveju galite grąžinti pirmąjį atitikimo raktą:

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

Taip pat „Guava“ naudotojams „ BiMap“ gali būti naudinga. Pavyzdžiui:

 BiMap<Token, Character> tokenToChar = ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '('); Token token = tokenToChar.inverse().get('('); Character c = tokenToChar.get(token); 
569
25 мая '10 в 14:53 2010-05-25 14:53 atsakymą pateikė Vitalii Fedorenko , gegužės 25 d., 10 val. 14:53 2010-05-25 14:53
 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()); } } } } 

Daugiau informacijos ... Gal galite padėti.

Pirmiau nurodytas metodas gali būti labai geras, jei jūsų maišos failas yra labai didelis. Jei jūsų maišos faile yra unikalus raktas, skirtas unikaliajai reikšmių kartografavimui, galite išsaugoti kitą maišos failą, kuriame yra atvaizdavimas iš vertės į raktą.

Tai yra, jums reikia išsaugoti du hashmaps

 1. Key to value 2. Value to key 

Tokiu atveju, norėdami gauti raktą, galite naudoti antrąjį maišos failą.

71
12 окт. Atsakymą pateikė Fathah Rehman P 12 spalis. 2011-10-12 11:48 '11, 11:48, 2011-10-12 11:48

Galite įterpti raktą, vertę ir inversiją į savo žemėlapio struktūrą.

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

Naudojant map.get ("theValue") grįš "theKey".

Tai greitas ir purvinas būdas sukurti nuolatinius žemėlapius, kurie veiks tik keliems duomenų rinkiniams:

  • Yra tik 1–1 poros.
  • Nustatyta reikšmė nesiskiria su rakto rinkiniu (1-> 2, 2-> 3 pertrauka)
18
19 нояб. Atsakymą pateikė Chicowitz lapkričio 19 d. 2013-11-19 20:18 '13, 20:18, 2013-11-19 20:18

Manau, kad jūsų pasirinkimas

  • Tam naudokite žemėlapio įgyvendinimą, pvz., „ BiMap“ iš „Google“ kolekcijų. Atkreipkite dėmesį, kad „Google BiMap“ kolekcijoms reikalingos unikalios vertės ir raktai, tačiau tai užtikrina aukštą našumą abiejose veiklos srityse.
  • Rankiniu būdu išsaugokite dvi korteles - vieną kiekvienam raktui → reikšmę ir kitą reikšmę → klavišą
  • Eikite per entrySet() ir suraskite raktus, kurie atitinka šią vertę. Tai pats lėčiausias metodas, nes tam reikia iteracijos visoje kolekcijoje, o kiti du metodai to nereikalauja.
17
05 сент. Atsakymas pateikiamas Chi 05 Sep. 2009-09-05 20:57 '09 ne 20:57 2009-09-05 20:57

Papuoškite kortelę su savimi

 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); } } 
11
23 мая '16 в 16:10 2016-05-23 16:10 Atsakymą teikia ABHI gegužės 23 d., 16 val. 16:10 2016-05-23 16:10

Jei norite rasti visus raktus, kurie priskiria šią vertę, kartokite per visas maišos žemėlapio poras, naudodami map.entrySet() .

11
05 сент. Atsakymas pateikiamas wsorenson 05 Sep. 2009-09-05 20:10 '09, 20:10, 2009-09-05 20:10

Nėra jokio vienareikšmio atsakymo, nes keli mygtukai gali būti rodomi ta pačia verte. Jei naudojate unikalumą su savo kodu, geriausias sprendimas yra sukurti klasę, kuri naudoja dvi Hashmaps, kad stebėtų rungtynes ​​abiem kryptimis.

11
05 сент. atsakymas duotas rekursyviam 05 sep. 2009-09-05 20:08 '09, 08:08, 2009-09-05 20:08

Manau, kad tai geriausias sprendimas, originalus adresas: „ Java2“

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

Paprastas naudojimas: jei įdėjote visus duomenis į „hasMap“ ir turite elementą = „Automobiliai“, tada ieškote jos rakto „hashMap“. Tai geras sprendimas.

 getKeyFromValue(hashMap, item); System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item)); 
8
09 февр. atsakymas suteiktas berniui 09 vasaris. 2015-02-09 20:19 '15, 20:19, 2015-02-09 20:19

Jei sukursite žemėlapį savo kode, pabandykite įdėti raktą ir vertę žemėlapyje:

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

Tada, kai turite vertę, taip pat turite raktą.

7
05 сент. Atsakyti David Tinker Sep 05 2009-09-05 20:58 '09 ne 20:58 2009-09-05 20:58

Atrodo, kad geriau map.entrySet() įrašus naudodami map.entrySet() , nes map.containsValue() tikriausiai tai daro.

6
05 сент. Atsakymą pateikė Jonas Klemming 05 Sep. 2009-09-05 20:12 '09, 20:12, 2009-09-05 20:12

Bijau, kad tiesiog turite išsirinkti savo kortelę. Trumpai tariant, galėčiau pateikti:

 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
28 мая '10 в 12:52 2010-05-28 12:52 atsakė André van Toly'ui gegužės 10 d., 10 val. 12:52 2010-05-28 12:52
 for(int key: hm.keySet()) { if(hm.get(key).equals(value)) { System.out.println(key); } } 
6
05 авг. atsakymą pateikė user309309 05 rug . 2015-08-05 15:31 '15 15:31 2015-08-05 15:31

Naudojant „Java 8“:

 ftw.forEach((key, value) -> { if (value=="foo") { System.out.print(key); } }); 
5
09 сент. Atsakymą pateikė phani 09 Sep. 2015-09-09 12:12 '15 , 12:12 2015-09-09 12:12

Su „Android“ orientuotu taikymu <19, „Vitaly Fedorenko“ „vienas su vienu“ sprendimas neveikia, nes Objects.equals neįgyvendinami. Čia yra paprasta alternatyva:

 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; } 
5
14 апр. Atsakymą pateikė „ The Berga“ 14 d. 2016-04-14 17:14 '16 at 17:14 pm 2016-04-14 17:14

Galite naudoti žemiau:

 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); } } } } 
3
10 нояб. atsakymą pateikė Balasubramanian Ganapathi lapkričio 10 d. 2016-11-10 02:00 '16 at 2:00 2016-11-10 02:00
 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; } 
2
22 июня '17 в 10:34 2017-06-22 10:34 atsakymą pateikė „ Amazing India “ birželio 22 d. 17 d. 10:34 2017-06-06 10:34

Raktą galite gauti naudodami tokį kodą.

 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
11 июня '10 в 11:36 2010-06-11 11:36 atsakymas pateikiamas Amit birželio 11 d., 10 val. 11:36 2010-06-11 11:36
 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
12 дек. atsakymas pateikiamas 12 d. 2012-12-12 23:24 '12, 23:24, 2012-12-12 23:24

Nors jis neatsako tiesiogiai į klausimą, jis yra prijungtas.

Taigi jums nereikia toliau kurti / pakartoti. Tiesiog sukurkite atvirkštinį žemėlapį vieną kartą ir gaukite tai, ko jums reikia.

  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; }  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; } 
1
02 февр. Markymark atsakymas 02 vasaris 2018-02-02 02:22 '18 at 2:22 2018-02-02 02:22

Naudokite ploną apvalkalą: „ 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
22 окт. Atsakymą pateikė Jayen spalio 22 d. 2011-10-22 09:14 '11 at 9:14 2011-10-22 09:14

Taip, jums reikia eiti per maišos kortelę, jei jūs neįgyvendinate kažko pagal šiuos skirtingus atsakymus. Vietoj to, kad netrukdytumėte įrašų rinkinio, aš tiesiog gaunu „keySet“ (), kilpą per rinkinį ir išsaugoju (pirmąjį) raktą, kuris gauna jūsų atitinkamą vertę. Jei jums reikia visų raktų, atitinkančių šią vertę, akivaizdu, kad tai reikia padaryti.

Kaip sako Jonas, tai jau gali būti tai, ką apima „ValueValue“ metodas, todėl galite tiesiog praleisti šį testą kartu ir tiesiog kartoti kiekvieną kartą (arba galbūt kompiliatorius jau pašalins atleidimą iš darbo, kas žino).

Taip pat atsižvelgiant į kitus atsakymus, jei atrodo, kad jūsų sugrįžimo kortelė atrodo

 Map<Value, Set<Key>> 

jei jums reikalinga ši galimybė (galite ištrinti juos į šoną), galite tvarkyti ne unikalius raktų-> vertės žemėlapius. Jis puikiai tinka bet kuriam čia siūlomam sprendimui, naudojant dvi korteles.

1
05 сент. atsakymą pateikė Carl Sep 05 2009-09-05 22:45 '09 10:45 val. 2009-09-05 22:45
 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
07 авг. atsakymas duotas Madhav 07 rug. 2012-08-07 20:34 '12 8:34 pm 2012-08-07 20:34

Mano 2 centai. Jūs galite gauti raktus masyvu ir paskui kilti iš masyvo. Tai turės įtakos šio kodo bloko veikimui, jei kortelė yra gana didelė, kur jūs gaunate raktus masyve, kuris gali suvartoti šiek tiek laiko, ir tada jūs sugedate. Priešingu atveju mažoms kortelėms tai turėtų būti normalus.

 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
05 июля '16 в 15:52 2016-07-05 15:52 atsakymą pateikė „ Manu Bhat “ liepos 5 d. 16 d. 15:52 2016-07-05 15:52
 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; }  } 
1
22 авг. Kanagavelu Sugumar rugpjūčio 22 d. Atsakymas 2013-08-22 20:53 '13, 20:53, 2013-08-22 20:53
  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
06 мая '15 в 23:35 2015-05-06 23:35 atsakymas pateikiamas kanaparthikiran gegužės 06 d. 15, 23:35 2015-05-06 23:35

„Java8“

 map.entrySet().stream().filter(entry -> entry.getValue().equals(value)) .forEach(entry -> System.out.println(entry.getKey())); 
0
10 июня '14 в 4:53 2014-06-10 04:53 atsakymą pateikė vartotojo3724331 birželio 10 d. 14 val. 4:53 2014-06-10 04:53
  • Jei norite gauti vertės raktą, geriausia naudoti bidimap (dvikryptis korteles), galite gauti reikšmės raktą O (1).

    Tačiau trūkumas yra tas, kad galite naudoti tik unikalų raktų ir vertybių rinkinį.

  • „Java“ turi duomenų struktūrą, vadinamą lentele , kuri yra ne tik tipo žemėlapis

    Lentelė <A, B, C> == žemėlapis <A, žemėlapis <B, C →

    Čia galite gauti map<B,C> prašant T.row(a); , taip pat galite gauti map<A,C> , prašydami T.column(b);

Savo ypatingu atveju įterpkite C kaip pastovią.

Taigi tai yra kaip <a1, b1, 1> <a2, b2, 1>, ...

Taigi, jei surasite per T.row (a1) ---> grįžtamasis žemėlapis → gaus raktus, tai yra grįžtamasis žemėlapis.

Jei reikia rasti raktų reikšmę, tada T.column (b2) → grąžina žemėlapį → gauna grąžinto žemėlapio raktus.

Privalumai, palyginti su ankstesniu atveju:

  • Gali naudoti kelias reikšmes.
  • Efektyvesnis naudojant didelius duomenų rinkinius.
0
29 авг. atsakymas pateikiamas Batman 29 rug. 2016-08-29 09:25 '16 at 9:25 am 2016-08-29 09:25

Kiek aš žinau, „HashMap“ klavišai ir reikšmės nesumaišomi, kai juos vaizduojate kaip masyvus:

 hashmap.values().toArray() 

ir taip pat

 hashmap.keySet().toArray() 

Todėl šis kodas (pradedant „Java 8“) turėtų veikti taip:

 public Object getKeyByFirstValue(Object value) { int keyNumber = Arrays.asList(hashmap.values().toArray()).indexOf(value); return hashmap.keySet().toArray()[keyNumber]; } 

Tačiau ( DĖMESIO! ) Jis veikia 2-3 kartus lėčiau nei iteracija.

0
14 нояб. Atsakymą pateikė MilTy lapkričio 14 d. 2018-11-14 03:02 '18 at 3:02 2018-11-14 03:02

Svarbu pažymėti, kad šiuo klausimu „Apache“ kolekcijos palaiko „ General BidiMaps“ . Taigi kai kurie geriausi apklausos atsakymai šiuo klausimu nebėra tikslūs.

Serializuotam „BidiMap“, kuris taip pat palaiko dvigubas vertes („vienas su daugeliu“), taip pat apsvarstykite MapDB.org .

0
31 мая '15 в 19:25 2015-05-31 19:25 atsakymą pateikė kervin gegužės 15 d. 15:25 2015-05-31 19:25
  • 1
  • 2

Kiti klausimai apie „ arba „ Klauskite“