Java Hashmap: Değerden anahtar nasıl alınır?


452

Değeri varsa "foo"ve HashMap<String> ftwhangi ftw.containsValue("foo")döndürürse true, karşılık gelen anahtarı nasıl alabilirim? Haşhaştan geçmek zorunda mıyım? Bunu yapmanın en iyi yolu nedir?


72
Tek bir karşılık gelen anahtar olmadığını unutmayın - aynı değere eşlenen birden fazla anahtar olabilir.
CPerkins

1
@CPerkinler ancak <strFilename, Reader> ve diğerleri 1'e 1 gibi hashitler için çok kullanışlıdır.
Kova Gücü

küçük bir ürün koleksiyonunuz varsa, sabit oluşturmayı düşünün public static final String TIME = "time";veproperties.put(TIME, PbActivityJpa_.time);
Basheer AL-MOMANI

muhtemelen bu haritadan veri elde etmenize yardımcı olabilir ve siz de bir çeşit İşleme yapabilirsiniz. frugalisminds.com/java/java-8-stream-map-examples
Sanjay-Dev

Yanıtlar:


215

Standart Java Collections API'sı yerine Commons Collections kitaplığını kullanmayı seçerseniz , bunu kolayca başarabilirsiniz.

BidiMap Koleksiyonları kütüphanede arayüzü (normal haritalar gibi) bir değere Bir anahtar eşleştirmek sağlayan çift yönlü haritası, ve ayrıca böylece her iki yönde aramaları gerçekleştirmek için izin, bir anahtara bir değer haritaya. Bir değer için anahtar edinmek, getKey () yöntemi tarafından desteklenir .

Bununla birlikte, bidi haritaların anahtarlarla eşlenmiş birden fazla değeri olamaz ve bu nedenle veri kümenizde anahtarlar ve değerler arasında 1: 1 eşleme yoksa, teklif haritalarını kullanamazsınız.

Güncelleme

Java Collections API'sına güvenmek istiyorsanız, değeri haritaya eklerken anahtarlar ve değerler arasında 1: 1 ilişkisini sağlamanız gerekir. Bunu söylemek yapmaktan daha kolay.

Bundan emin olduktan sonra , Haritadaki girdi kümesini (eşlemeler) elde etmek için entrySet () yöntemini kullanın. Türü Map.Entry olan seti edindikten sonra, saklanan değeri beklenen değerle karşılaştırarak girişler arasında yineleyin ve karşılık gelen anahtarı elde edin .

Güncelleme # 2

Jenerikler ile bidi haritaları için destek Google Guava ve yeniden yapılandırılmış Commons-Collections kütüphanelerinde bulunabilir (ikincisi bir Apache projesi değildir). Apache Commons Koleksiyonlarındaki eksik genel desteği belirttiği için Esko'ya teşekkürler. Koleksiyonların jeneriklerle kullanılması, daha sürdürülebilir bir kod oluşturur.


23
... ve Generics'i ve tüm bu modern şeyleri seviyorsanız, Google Koleksiyonlar BiMap'e sahiptir ve burada biMap.inverse ().
Esko

1
Evet, Apache Commons Collections jenerikleri desteklemez. Ancak, işaret ettiğiniz gibi Google Koleksiyonları var (henüz kullanmadım - henüz 1.0 sürümü yok) ve Generics'i destekleyen yeniden düzenlenmiş Commons Koleksiyonları var. Bunu bir Sourceforge projesi olarak bulacaksınız @ sourceforge.net/projects/collections
Vineet Reynolds

2
Google Koleksiyonlar, Commons-Collections'ın yeniden düzenlenmiş bir sürümü değildir .
whiskysierra

12
@whiskeysierra: Hiç kimsenin bunu söylemediğini sanmıyorum.
huysuzluk

2

603

Veri yapınızda anahtarlar ve değerler arasında bire bir eşleme varsa, girişler üzerinde tekrarlamalı ve tüm uygun anahtarları seçmelisiniz:

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

Durumunda bire bir ilişki, öncelikle eşleşti anahtarı dönebilirsiniz:

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'de:

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

Ayrıca, Guava kullanıcıları için BiMap yararlı olabilir. Örneğin:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);

3
Performans hakkında bir şey söyleyebilir misin? Daha ne optimize edilecek? Bu veya BidiMap?
tasomaniac

Aynı çözümü düşündüm, elbette iptal ettim ama gerçekten büyük Koleksiyonlar söz konusu olduğunda verimliliğinden şüphe ediyorum.
arjacsoh

3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap'ın zaman karmaşıklığı vardır o(1). Değerler üzerinde yineleme yapıyorsanız, performansı öldürür. Eğer istiyorsanız better performanceve bir one-oneilişkisi varsa, another mapnerede kullanabilirsinizvalue is a key
veer7

3
Ben yeteneği hakkında hiçbir açıklama yapıldı gibi .filter(entry -> entry.getValue().equals(value))ile değiştirmenizi öneririz . Ayrıca, sen yerine sahip.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Holger

Set <T> getKeysByValue () önce <T, E> gösterimi anlamakta zorluk yaşıyorum ... ne anlamı .... bunu kullanmadan yapmak için farklı bir yol? teşekkürler
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());
            }
        }
    }
}

Bazı ek bilgiler ... Sizin için yararlı olabilir

Eğer hashutunuz gerçekten büyükse yukarıdaki yöntem iyi olmayabilir. Hashmap'iniz benzersiz değer eşlemesi için benzersiz bir anahtar içeriyorsa, Value ile Key arasında eşleme içeren bir hashmap daha sağlayabilirsiniz.

Yani iki hasheti korumak zorundasın

1. Key to value

2. Value to key 

Bu durumda anahtar almak için ikinci hashmap kullanabilirsiniz.


19

Bence seçimlerin

  • BiMap gibi bunun için oluşturulmuş bir harita uygulaması kullanınGoogle koleksiyonlarından . Google koleksiyonları BiMap'in benzersiz değerlerin yanı sıra anahtarlar gerektirdiğini, ancak her iki yön performansında da yüksek performans sağladığını unutmayın
  • Biri anahtar -> değer ve değeri için başka bir harita -> tuşu olan iki haritayı el ile koruyun
  • Değerle entrySet()eşleşen anahtarları bulmak için ve düğmelerini yineleyin . Bu en yavaş yöntemdir, çünkü tüm koleksiyon boyunca yineleme gerektirirken, diğer iki yöntem bunu gerektirmez.

19

Harita yapınıza hem anahtar, değer çifti hem de tersini ekleyebilirsiniz

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

Map.get ("theValue") kullanıldığında "theKey" döndürülür.

Bu, yalnızca belirli birkaç veri kümesi için çalışacak olan sabit haritalar yapmamın hızlı ve kirli bir yoludur:

  • Sadece 1 ila 1 çift içerir
  • Değer kümesi anahtar kümesinden ayrılır (1-> 2, 2-> 3 keser)

4
Bu gerçekten doğru değil. Bu sadece 1-1 gerektirmez, aynı zamanda değer kümesinin anahtar kümesinden ayrılmasıdır. Bunu {1 -> 2, 2 -> 3} iki yönlü haritasına uygulayamazsınız: 2 hem bir değer hem de bir anahtardır.
Luis A. Florit

15

Haritayı kendi uygulamanızla süsleyin

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

Bu ilginç bir yaklaşım olduğunu düşünüyorum, ancak ilişki 1: 1 olması gerektiğinden, HashMap'den tamamen kurtulur ve bunun yerine Map <K, V> arayüzünü uygular, böylece hem değerlerin hem de anahtarların kopyalarını önlemek için.
Fran Marzoa

11

Kesin bir cevap yoktur, çünkü birden fazla anahtar aynı değere eşlenebilir. Kendi kodunuzla benzersizliği uygularsanız, en iyi çözüm eşlemeleri her iki yönde izlemek için iki Hashmap kullanan bir sınıf oluşturmaktır.


11

Bu değerle eşleşen tüm anahtarları bulmak için, hashmap içindeki tüm çiftleri kullanarak tekrarlayın map.entrySet().


4
Bu çözüm, büyük HashMaps üzerinde pratik olmadığı noktaya kadar çok yoğundur.
Joehot200

10

Java 8'i kullanma:

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

6
value=="foo" bu işe yaramaz. equalsDizeleri karşılaştırmak için kullanılmalıdır.
Anton Balaniuc

@Anton, stajyer olmadıkça doğru value.
frododot

9

Haritayı kendi kodunuzda oluşturursanız, anahtarı ve değeri haritaya bir araya getirmeyi deneyin:

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

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

Sonra bir değeriniz olduğunda, anahtar da vardır.


3
Zeki, ama aynı değeri içeren 2 veya daha fazla KeyValue nesnesi varsa ne olur? Hangi anahtar seçilmelidir?
Vineet Reynolds

2
@Vineet, bu yaklaşımın OP'nin sorusunu nasıl çözdüğünü görmüyorum. "Öyleyse bir değerin olduğunda, anahtarın da var." ile ne demek istedin?
Qiang Li

9

Bence bu en iyi çözüm, orijinal adres: 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;
          }
        }

Kolay kullanım: tüm verileri hasMap içine koyarsanız ve item = "Automobile" a sahipseniz, anahtarını hashMap'ta arıyorsunuz. bu iyi bir çözümdür.

getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));

7

Korkarım sadece haritanızı tekrarlamanız gerekecek. En kısa ben gelebilir:

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

Kullandığınız girdileri üzerinde yineleme yapmak için en iyi yoldur gibi geliyor map.entrySet()çünkü map.containsValue()muhtemelen bu zaten yok.


Evet, aynen öyle. Ama elbette OP'nin muhtemelen yapması gerekenin aksine .equals'ın doğru olduğu bir değer bulur bulmaz doğruya döner.
CPerkins

1
Girişleri yinelemek, eşleşen bir değer bulur bulmaz anahtar ile dönebilir. Birden fazla eşleşme endişe verici görünmüyordu.
Jonas K

6

Android geliştirme hedefleme API'sı <19 için, Vitalii Fedorenko bire bir ilişki çözümü işe yaramadığı için çalışmıyor Objects.equals. İşte basit bir alternatif:

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

Bu çözüm benim için çalışıyor; ayrıca arkeolojik bir Android sürümü için geliştiriyorum, benim durumumda bir Harita üzerinde bir "onMarkerClick" etkinliğinde düzenlenen bir Google Harita işaretleyicisinin anahtarını almak için. EntrySet çalışmalarını yineleme; ancak anahtarları yineleyip get () ile girişlerle eşleştirmek ve çıktıyı karşılaştırmak vermedi.
Toby Wilson

3

Aşağıdakileri kullanabilirsiniz:

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

Yararlı şeyler sağlamak istediğiniz güzel, ancak "yalnızca kod" yanıtı olmamalı ve kodun kendisi de kod kokularıyla dolu olmamalıdır.
Tom

2

Evet, bu çeşitli cevapların önerdiği şeyler boyunca bir şey uygulamadığınız sürece, hashmap arasında döngü yapmalısınız. İnputSet ile uğraşmak yerine, keySet () 'i alıyorum, bu set üzerinde tekrar ediyorum ve eşleşen değerinizi alan (ilk) anahtarı saklıyorum. Bu değerle eşleşen tüm anahtarlara ihtiyacınız varsa, her şeyi yapmanız gerekir.

Jonas'ın önerdiği gibi, bu zaten includeValue yönteminin yaptığı şey olabilir, bu yüzden bu testi hep birlikte atlayabilir ve her seferinde yinelemeyi yapabilirsiniz (veya derleyici zaten gereksizliği ortadan kaldıracaktır, kim bilir).

Ayrıca, ters haritanız aşağıdaki gibi görünüyorsa, diğer cevaplara göre

Map<Value, Set<Key>>

bu özelliğe ihtiyacınız varsa benzersiz olmayan anahtar-> değer eşleştirmeleriyle başa çıkabilirsiniz (bunları bir kenara bırakabilirsiniz). Bu, insanların burada iki harita kullanarak önerdikleri çözümlerden herhangi birine iyi bir katkı sağlayacaktır.


2

Aşağıdaki kodu kullanarak değerleri kullanarak anahtarı alabilirsiniz ..

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

}

Bence bu cevap bir açıklama ekleyerek geliştirilebilir.
Jonathan

2
-1. StringAnahtar ve değer olarak test ettim . Aradığımda , anahtar olsa bile map.add("1", "2"); map.add("1","3");, arayabilir map.getKey("2");ve geri alabilirim . "1""1""3"
jlordo

@Jonathan bu sınıfın arkasındaki fikir, bir anahtardan bir değer almanın yanı sıra, bir değerden bir anahtar da alabilmeniz için ters eşlemelere sahip başka bir HashMap tutmaktır. T1 ve T2 sınıfları biraz kafa karıştırıcı; belki tam anlamıyla onlara Anahtar ve Değer adını? Her ne kadar verilere ve ne istediğinize bağlı olarak birden fazla değer veya birden fazla anahtar alma yeteneğini beklesem de. Dikkatli kullanın
Chicowitz

1
@theknightwhosaysni "1" artık "2" nin anahtarı değil. Bu aynı zamanda sorunuzun cevabıdır, arama getValue("1")geri döner 3.
jlordo

Üzgünüz jlordo, standart Hashmap davranışı hakkında yanılmışım: bir anahtar için yeni bir değer eklemenin eski değerin yerini alması doğru
Chicowitz

2

Java8'de

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 = yeni HashMap <String, Integer> (); map.put ("A", 1); map.put ("B", 2); map.put ("C", 3); map.put ("D", 4); // System.out.println (harita); System.out.println (getKey (harita, "4"));
İnanılmaz Hindistan

1
Birden fazla anahtar aynı değere sahipse ne olur?
Cà phê đen

Eğer u geçmek birden fazla anahtar aynı değere sahip, biz sonuç olarak son anahtar alırsınız. örnek: A 1, B 1, C 1, D 2 çıkışı: 1 değerini
Amazing India

@AmazingIndia Bu garanti edilmez ve tamamen belirli harita uygulamasına bağlıdır. Örneğin HashMap bir siparişi garanti etmez, bu nedenle burada hangi çıktının döndürüleceği hakkında hiçbir fikriniz yoktur.
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

İnce bir ambalaj kullanın: 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

Benim 2 sentim. Bir dizideki anahtarları alabilir ve sonra dizi boyunca döngü yapabilirsiniz. Harita oldukça büyükse, bu kod bloğunun performansını etkiler, burada bir dizideki anahtarları ilk önce biraz zaman harcayabilir ve daha sonra döngüye girersiniz. Aksi takdirde daha küçük haritalar için uygun olmalıdır.

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

Ve neden birisi bu yaklaşımı kullanmalı? Daha önce de söylediğin gibi, performans diğer yaklaşımlardan daha kötü olurdu.
Tom

1

Bence anahtar kümesi () değerine eşleme anahtarları bulmak ve daha iyi bir kodlama stili var iyi olabilir entrySet () .

Ör:

Bir HashMap haritanız olduğunu varsayalım , ArrayList res , tüm anahtar eşlemesini bulmak istediğiniz bir değer , ardından anahtarları res'de saklayın .

Aşağıya kod yazabilirsiniz:

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

aşağıdaki inputSet () yöntemini kullanmak yerine:

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

Umarım yardımcı olur :)


map.get(key) == valuereferansları karşılaştırırken nesnelerin eşitliğini kontrol ederken iyi bir fikir değildir. Nesne eşitliği her zaman kullanmalı.equals()
frododot

1

Bu doğrudan soruyu cevaplamasa da, ilişkilidir.

Bu şekilde oluşturmaya / yinelemeye devam etmenize gerek kalmaz. Sadece bir kez ters harita oluşturun ve ihtiyacınız olanı alın.

/**
 * 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
  1. Eğer değerden anahtar almak istiyorsanız, en iyi teklif haritasını (iki yönlü haritalar) kullanmak istiyorsanız, O (1) zamanında değerden anahtar alabilirsiniz.

    Ancak, bunun dezavantajı sadece benzersiz tuş takımı ve değer kümesi kullanabilmenizdir.

  2. Adlı bir veri yapısı vardır Tablo gibi haritaların başka bir şey haritasıdır java,

    Tablo <A, B, C> == harita <A, harita <B, C>>

    Burada alabilirsiniz map<B,C>sorgulama ile T.row(a);ve ayrıca alabilirsiniz map<A,C>sorgulama tarafındanT.column(b);

Özel durumunuzda, C'yi bir miktar sabit olarak yerleştirin.

Yani, <a1, b1, 1> <a2, b2, 1> gibi ...

Yani, T.row (a1) ---> ile bulursanız -> döndürür harita -> get keyset bu döndürülen harita.

Anahtar değerini bulmanız gerekiyorsa, T.column (b2) -> döndürülen haritanın -> döndürülen haritanın anahtar kümesini al.

Önceki davaya göre avantajları:

  1. Birden çok değer kullanabilir.
  2. Büyük veri kümeleri kullanırken daha verimli.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.