Java Hashmap: Bagaimana cara mendapatkan kunci dari nilai?


450

Jika saya memiliki nilai "foo", dan nilai HashMap<String> ftwyang ftw.containsValue("foo")kembali true, bagaimana saya bisa mendapatkan kunci yang sesuai? Apakah saya harus mengulang hashmap? Apa cara terbaik untuk melakukannya?


72
Perhatikan bahwa tidak ada kunci tunggal yang sesuai - mungkin ada beberapa pemetaan kunci dengan nilai yang sama.
CPerkins 06

1
@CPerkins tetapi untuk hashmaps seperti <strFilename, Reader>, dan banyak lainnya 1 banding 1, ini sangat berguna.
Aquarius Power

jika Anda memiliki koleksi barang kecil, pertimbangkan untuk membuat konstanta public static final String TIME = "time";danproperties.put(TIME, PbActivityJpa_.time);
Basheer AL-MOMANI

mungkin ini bisa membantu Anda mendapatkan data dari peta dan Anda dapat melakukan semacam pemrosesan juga. frugalisminds.com/java/java-8-stream-map-examples
Sanjay-Dev

Jawaban:


215

Jika Anda memilih untuk menggunakan pustaka Commons Collections alih-alih API Java Collections standar, Anda dapat melakukannya dengan mudah.

The BidiMap antarmuka di perpustakaan Koleksi adalah peta bi-directional, yang memungkinkan Anda untuk memetakan kunci untuk nilai (seperti peta normal), dan juga untuk memetakan nilai untuk kunci, sehingga memungkinkan Anda untuk melakukan pencarian di kedua arah. Mendapatkan kunci untuk suatu nilai didukung oleh metode getKey () .

Namun ada peringatan, peta bidi tidak dapat memiliki beberapa nilai yang dipetakan ke kunci, dan karenanya kecuali kumpulan data Anda memiliki pemetaan 1: 1 antara kunci dan nilai, Anda tidak dapat menggunakan bidimaps.

Memperbarui

Jika Anda ingin mengandalkan Java Collections API, Anda harus memastikan hubungan 1: 1 antara kunci dan nilai pada saat memasukkan nilai ke dalam peta. Ini lebih mudah dikatakan daripada dilakukan.

Setelah Anda bisa memastikannya, gunakan metode entrySet () untuk mendapatkan set entri (pemetaan) di Peta. Setelah Anda mendapatkan set yang jenisnya adalah Map.Entry , beralih melalui entri, membandingkan nilai yang disimpan dengan yang diharapkan, dan mendapatkan kunci yang sesuai .

Perbarui # 2

Dukungan untuk peta bidi dengan obat generik dapat ditemukan di Google Guava dan perpustakaan Commons-Collections refactored (yang terakhir bukan proyek Apache). Terima kasih kepada Esko untuk menunjukkan dukungan generik yang hilang di Apache Commons Collections. Menggunakan koleksi dengan obat generik membuat kode lebih mudah dikelola.


23
... dan jika Anda menyukai Generics dan semua barang modern itu, Google Collections memiliki BiMap tempat Anda bisa mendapatkan nilai yang cocok dengan kunci yang ditentukan dengan menelepon biMap.inverse (). get (value);
Esko

1
Ya, Koleksi Apache Commons tidak mendukung obat generik. Namun, ada Google Collections seperti yang telah Anda tunjukkan (yang belum saya gunakan - belum ada rilis 1.0), dan ada Commons-Collections yang dire-refactored dengan dukungan untuk Generics. Anda akan menemukan ini sebagai proyek Sourceforge @ sourceforge.net/projects/collections
Vineet Reynolds

2
Google Collections bukan versi Commons-Collections yang telah di-refactored.
whiskeysierra

12
@ whiskeysierra: Saya tidak berpikir ada orang (saat ini) mengatakan demikian.
Huff

2
Koleksi Apache sekarang mendukung generics commons.apache.org/proper/commons-collections/javadocs/…
kervin

603

Jika struktur data Anda memiliki banyak-ke-satu pemetaan antara kunci dan nilai-nilai Anda harus mengulangi entri dan memilih semua kunci yang sesuai:

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

Dalam kasus hubungan satu-ke-satu , Anda dapat mengembalikan kunci yang cocok pertama:

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

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

Juga, untuk pengguna Guava, BiMap mungkin berguna. Sebagai contoh:

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

3
Bisakah Anda mengatakan sesuatu tentang kinerja? Apa yang akan lebih dioptimalkan? Ini atau BidiMap?
tasomaniac

Saya telah memikirkan solusi yang sama, tentu saja saya telah memutakhirkannya tetapi saya ragu akan efisiensinya dalam hal Koleksi yang sangat besar.
arjacsoh

3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap memiliki kompleksitas waktu o(1). Jika Anda mengulangi nilai-nilai maka itu akan mematikan kinerja. Jika Anda menginginkan better performancedan memiliki one-onehubungan, Anda dapat menggunakan di another mapmanavalue is a key
veer7

3
Saya merekomendasikan untuk mengganti .filter(entry -> entry.getValue().equals(value))dengan karena tidak ada pernyataan tentang kemampuan dibuat. Selanjutnya, Anda dapat mengganti dengan.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Holger

Saya mengalami kesulitan memahami notasi <T, E> sebelum Set <T> getKeysByValue () ... apa gunanya .... cara yang berbeda untuk melakukannya tanpa menggunakan itu? terima kasih
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());
            }
        }
    }
}

Beberapa info tambahan ... Semoga bermanfaat bagi Anda

Metode di atas mungkin tidak baik jika hashmap Anda benar-benar besar. Jika hashmap Anda berisi kunci unik untuk pemetaan nilai unik, Anda dapat mempertahankan satu hashmap lain yang berisi pemetaan dari Value to Key.

Itu adalah Anda harus mempertahankan dua hashmaps

1. Key to value

2. Value to key 

Dalam hal ini Anda dapat menggunakan hashmap kedua untuk mendapatkan kunci.


19

Saya pikir pilihan Anda adalah

  • Gunakan implementasi peta yang dibuat untuk ini, seperti BiMap dari koleksi google. Perhatikan bahwa koleksi google BiMap memerlukan nilai unik, serta kunci, tetapi memberikan kinerja tinggi di kedua arah kinerja
  • Secara manual pertahankan dua peta - satu untuk kunci -> nilai, dan peta lainnya untuk nilai -> kunci
  • Iterate melalui entrySet()dan untuk menemukan kunci yang cocok dengan nilai. Ini adalah metode paling lambat, karena membutuhkan pengulangan melalui seluruh koleksi, sedangkan dua metode lainnya tidak memerlukan itu.

19

Anda bisa memasukkan kunci, pasangan nilai dan kebalikannya ke dalam struktur peta Anda

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

Menggunakan map.get ("theValue") kemudian akan mengembalikan "theKey".

Ini cara cepat dan kotor yang saya buat peta konstan, yang hanya akan bekerja untuk beberapa set data tertentu:

  • Berisi hanya 1 hingga 1 pasang
  • Set nilai terpisah dari set kunci (1-> 2, 2-> 3 istirahat)

4
Ini tidak sepenuhnya benar. Ini tidak hanya membutuhkan 1-1, tetapi juga himpunan nilai terpisah dari himpunan kunci. Anda tidak dapat menerapkan ini pada peta bijective {1 -> 2, 2 -> 3}: 2 keduanya adalah nilai dan kunci.
Luis A. Florit

15

Hiasi peta dengan implementasi Anda sendiri

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

Saya pikir ini adalah pendekatan yang menarik, meskipun karena hubungannya harus 1: 1, saya akan menyingkirkan HashMap sama sekali dan mengimplementasikan antarmuka Map <K, V> jadi untuk menghindari duplikat dari keduanya, nilai dan kunci.
Fran Marzoa

11

Tidak ada jawaban yang jelas, karena beberapa kunci dapat memetakan ke nilai yang sama. Jika Anda menerapkan keunikan dengan kode Anda sendiri, solusi terbaik adalah membuat kelas yang menggunakan dua Hashmaps untuk melacak pemetaan di kedua arah.


11

Untuk menemukan semua kunci yang memetakan ke nilai itu, iterate melalui semua pasangan di hashmap, menggunakan map.entrySet().


4
Solusi ini sangat intensif, hingga tidak praktis pada HashMaps besar.
Joehot200

10

Menggunakan Java 8:

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

6
value=="foo" ini tidak akan berhasil. equalsharus digunakan untuk membandingkan Strings.
Anton Balaniuc

@Anton, benar kecuali valuetelah diinternir.
frododot

9

Jika Anda membangun peta dalam kode Anda sendiri, cobalah menyatukan kunci dan nilai dalam peta:

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

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

Kemudian ketika Anda memiliki nilai, Anda juga memiliki kuncinya.


3
Pintar, tetapi bagaimana jika ada 2 atau lebih objek KeyValue yang mengandung nilai yang sama? Kunci mana yang harus dipilih?
Vineet Reynolds

2
@Vineet, saya tidak melihat bagaimana pendekatan ini memecahkan pertanyaan OP. apa yang Anda maksud dengan "Lalu ketika Anda memiliki nilai, Anda juga memiliki kunci."
Qiang Li

9

Saya pikir ini adalah solusi terbaik, alamat asli: 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;
          }
        }

Penggunaan yang mudah: jika Anda meletakkan semua data di hasMap dan Anda memiliki item = "Automobile", maka Anda mencari kuncinya di hashMap. itu solusi yang bagus.

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

7

Saya khawatir Anda hanya perlu mengulang peta Anda. Terpendek saya bisa datang dengan:

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

Kedengarannya cara terbaik bagi Anda adalah beralih dari entri map.entrySet()karena map.containsValue()mungkin tetap melakukan ini.


Ya, itulah yang dilakukannya. Tetapi tentu saja ia mengembalikan true segera setelah ia menemukan satu nilai yang .equals adalah benar, sebagai lawan dari apa yang mungkin perlu OP lakukan.
CPerkins 06

1
Ya, iterasi dari entri dapat kembali dengan kunci segera setelah menemukan nilai yang cocok juga. Beberapa pertandingan sepertinya tidak menjadi perhatian.
Jonas K

6

Untuk API penargetan pengembangan Android <19, solusi hubungan satu-ke-satu Vitalii Fedorenko tidak berfungsi karena Objects.equalstidak diterapkan. Inilah alternatif sederhana:

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

Solusi ini bekerja untuk saya; juga mengembangkan untuk versi Android arkeologis, dalam kasus saya untuk mendapatkan kunci penanda Google Map yang diadakan di Peta dalam acara "onMarkerClick". Iterasi karya entrySet; tetapi iterasi kunci dan mencocokkannya dengan entri dengan get (), dan membandingkan output, tidak.
Toby Wilson

3

Anda dapat menggunakan di bawah ini:

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

Sangat menyenangkan bahwa Anda ingin memberikan hal-hal yang bermanfaat, tetapi itu seharusnya tidak menjadi jawaban "hanya kode" dan kode itu sendiri tidak boleh penuh dengan bau kode.
Tom

2

Ya, Anda harus mengulang-ulang hashmap, kecuali Anda menerapkan sesuatu sesuai dengan apa yang disarankan oleh berbagai jawaban ini. Daripada mengutak-atik entriSet, saya hanya mendapatkan keySet (), beralih di set itu, dan simpan kunci (pertama) yang memberi Anda nilai kecocokan Anda. Jika Anda membutuhkan semua kunci yang cocok dengan nilai itu, jelas Anda harus melakukan semuanya.

Seperti yang disarankan Jonas, ini mungkin sudah menjadi apa yang dilakukan oleh metode containValue, jadi Anda bisa melewatkan tes itu bersama-sama, dan lakukan iterasi setiap kali (atau mungkin kompiler sudah akan menghilangkan redundansi, siapa tahu).

Juga, relatif terhadap jawaban lain, jika peta terbalik Anda terlihat seperti

Map<Value, Set<Key>>

Anda dapat menangani pemetaan nilai-kunci yang tidak unik, jika Anda membutuhkan kemampuan itu (mengesampingkannya). Itu akan memasukkan baik ke salah satu solusi yang disarankan orang di sini menggunakan dua peta.


2

Anda bisa mendapatkan kunci menggunakan nilai menggunakan kode berikut ..

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

}

Saya pikir jawaban ini dapat ditingkatkan dengan menambahkan penjelasan.
Jonathan

2
-1. Saya mengujinya dengan Stringkunci dan nilai. Ketika saya menelepon map.add("1", "2"); map.add("1","3");maka saya bisa menelepon map.getKey("2");dan mengambil "1", meskipun "1"adalah kunci untuk "3".
jlordo

@ Jonathan ide di balik kelas ini adalah untuk menjaga HashMap lain dengan pemetaan terbalik sehingga selain mengambil nilai dari kunci, Anda dapat mengambil kunci dari nilai. Kelas T1 & T2 agak membingungkan; mungkin benar-benar menamainya Key & Value? Meskipun saya akan mengharapkan kemampuan untuk menerima lebih dari satu nilai atau lebih dari satu kunci sebagai imbalan, tergantung pada data & apa yang Anda inginkan. Gunakan dengan hati
Chicowitz

1
@theknightwhosaysni "1" bukan kunci untuk "2" (lagi). Ini juga jawaban untuk pertanyaan Anda, menelepon getValue("1")akan kembali 3.
jlordo

Maaf jlordo, saya salah tentang perilaku standar Hashmap: Anda benar bahwa menambahkan nilai baru untuk kunci harus menggantikan nilai lama
Chicowitz

2

Di 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 <String, Integer> (); map.put ("A", 1); map.put ("B", 2); map.put ("C", 3); map.put ("D", 4); // System.out.println (peta); System.out.println (getKey (peta, "4"));
Amazing India

1
Apa yang terjadi jika beberapa kunci memiliki nilai yang sama?
Cà phê đen

Ketika Anda melewati beberapa kunci memiliki nilai yang sama, kami akan mendapatkan kunci terakhir sebagai hasilnya. contoh: A 1, B 1, C 1, D 2 output: jika kita melewati nilai 1, output akan menjadi C
Amazing India

@AmazingIndia Ini tidak dijamin dan sepenuhnya tergantung pada implementasi peta spesifik. HashMap misalnya tidak menjamin pesanan, jadi Anda tidak tahu output apa yang akan dikembalikan di sini.
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

Gunakan pembungkus tipis: 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 sen saya. Anda bisa mendapatkan kunci dalam array dan kemudian loop melalui array. Ini akan mempengaruhi kinerja blok kode ini jika peta cukup besar, di mana Anda mendapatkan kunci dalam array pertama yang mungkin memakan waktu dan kemudian Anda mengulang. Kalau tidak, untuk peta yang lebih kecil seharusnya ok.

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

Dan mengapa seseorang harus menggunakan pendekatan itu? Seperti yang sudah Anda katakan, kinerjanya akan lebih buruk, daripada dalam pendekatan lain.
Tom

1

Saya pikir keySet () mungkin lebih baik untuk menemukan pemetaan kunci ke nilai, dan memiliki gaya pengkodean yang lebih baik daripada entrySet () .

Ex:

Misalkan Anda memiliki peta HashMap , resolusi ArrayList , nilai yang ingin Anda temukan semua pemetaan kuncinya , kemudian simpan kunci ke res tersebut .

Anda dapat menulis kode di bawah ini:

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

daripada menggunakan entrySet () di bawah:

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

Semoga bermanfaat :)


map.get(key) == valuebukan ide yang baik ketika memeriksa kesamaan objek, karena Anda membandingkan referensi. Persamaan objek harus selalu menggunakan.equals()
frododot

1

Meskipun ini tidak langsung menjawab pertanyaan, itu terkait.

Dengan cara ini Anda tidak perlu terus membuat / mengulangi. Cukup buat peta terbalik sekali dan dapatkan yang Anda butuhkan.

/**
 * 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

Penting untuk dicatat bahwa sejak pertanyaan ini, Koleksi Apache mendukung BidiMaps Generik . Jadi, beberapa jawaban pilihan teratas tidak lagi akurat pada titik itu.

Untuk BidiMap Serial yang juga mendukung nilai duplikat (skenario 1-ke-banyak) juga mempertimbangkan MapDB.org .


0
  1. Jika Anda ingin mendapatkan kunci dari nilai, yang terbaik untuk menggunakan bidimap (peta dua arah), Anda bisa mendapatkan kunci dari nilai dalam waktu O (1).

    Tapi, kekurangannya adalah Anda hanya bisa menggunakan keyset dan valueset unik.

  2. Ada struktur data yang disebut Tabel di java, yang tidak lain adalah peta seperti peta

    Tabel <A, B, C> == peta <A, peta <B, C>>

    Di sini Anda bisa mendapatkan map<B,C>dengan permintaan T.row(a);, dan Anda juga bisa mendapatkan map<A,C>dengan permintaanT.column(b);

Dalam kasus khusus Anda, masukkan C sebagai konstanta.

Jadi, ini seperti <a1, b1, 1> <a2, b2, 1>, ...

Jadi, jika Anda menemukan melalui T.row (a1) ---> mengembalikan peta -> dapatkan keyset peta yang dikembalikan ini.

Jika Anda perlu menemukan nilai kunci, T.column (b2) -> mengembalikan peta -> mendapatkan keyset dari peta yang dikembalikan.

Keuntungan dari kasus sebelumnya:

  1. Dapat menggunakan beberapa nilai.
  2. Lebih efisien saat menggunakan set data besar.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.