Java Hashmap: Làm thế nào để lấy khóa từ giá trị?


450

Nếu tôi có giá trị "foo", và một HashMap<String> ftwftw.containsValue("foo")lợi nhuận true, làm thế nào tôi có thể nhận chìa khóa tương ứng? Tôi có phải lặp qua hashmap không? Cách tốt nhất để làm điều đó là gì?


72
Lưu ý rằng không có khóa tương ứng duy nhất - cũng có thể có nhiều khóa ánh xạ tới cùng một giá trị.
CPerkins

1
@CPerkins nhưng đối với các hashtag như <strFilename, Reader> và nhiều cái khác từ 1 đến 1, nó rất hữu ích.
Sức mạnh Bảo Bình

nếu bạn có một bộ sưu tập nhỏ các vật phẩm, hãy cân nhắc việc tạo hằng số public static final String TIME = "time";properties.put(TIME, PbActivityJpa_.time);
Basheer AL-MOMani

có lẽ điều này có thể giúp bạn lấy dữ liệu từ bản đồ và bạn cũng có thể thực hiện một số loại Xử lý. frrifisminds.com/java/java-8-stream-map-examples
Sanjay-Dev

Câu trả lời:


215

Nếu bạn chọn sử dụng thư viện Bộ sưu tập Commons thay vì API Bộ sưu tập Java tiêu chuẩn, bạn có thể dễ dàng đạt được điều này.

Các BidiMap giao diện trong thư viện Bộ sưu tập là một bản đồ hai chiều, cho phép bạn ánh xạ một chìa khóa cho một giá trị (như bản đồ bình thường), và cũng có thể để ánh xạ một giá trị cho một chìa khóa, do đó cho phép bạn thực hiện tra cứu theo cả hai hướng. Lấy khóa cho một giá trị được hỗ trợ bởi phương thức getKey () .

Mặc dù có một cảnh báo, bản đồ thầu không thể có nhiều giá trị được ánh xạ tới các khóa và do đó trừ khi tập dữ liệu của bạn có ánh xạ 1: 1 giữa các khóa và giá trị, bạn không thể sử dụng giá thầu.

Cập nhật

Nếu bạn muốn dựa vào API Bộ sưu tập Java, bạn sẽ phải đảm bảo mối quan hệ 1: 1 giữa các khóa và giá trị tại thời điểm chèn giá trị vào bản đồ. Nói thì dễ hơn là làm.

Khi bạn có thể đảm bảo rằng, hãy sử dụng phương thức entryset () để lấy tập hợp các mục (ánh xạ) trong Bản đồ. Khi bạn đã nhận được tập hợp có loại là Map.Entry , lặp qua các mục, so sánh giá trị được lưu trữ với dự kiến ​​và lấy khóa tương ứng .

Cập nhật số 2

Có thể tìm thấy hỗ trợ cho các bản đồ thầu có tính tổng quát trong Google Guava và các thư viện Commons-Collections được tái cấu trúc (sau này không phải là một dự án Apache). Cảm ơn Esko vì đã chỉ ra sự hỗ trợ chung còn thiếu trong Bộ sưu tập Commons của Apache. Sử dụng các bộ sưu tập với generic giúp mã dễ bảo trì hơn.


23
... và nếu bạn thích Generics và tất cả những thứ hiện đại đó, Bộ sưu tập của Google có BiMap nơi bạn có thể nhận khóa khớp với giá trị được chỉ định bằng cách gọi biMap.inverse (). get (value);
Esko

1
Có, Bộ sưu tập Apache Commons không hỗ trợ thuốc generic. Tuy nhiên, có Bộ sưu tập Google như bạn đã chỉ ra (mà tôi chưa sử dụng - chưa có bản phát hành 1.0) và có Bộ sưu tập Commons được tái cấu trúc có hỗ trợ cho Generics. Bạn sẽ thấy đây là một dự án Sourceforge @ sourceforge.net/projects/collections
Vineet Reynold

2
Bộ sưu tập Google không phải là phiên bản được tái cấu trúc của Bộ sưu tập chung.
whiskeyierra

12
@whiskeysierra: Tôi không nghĩ có ai (hiện tại) nói như vậy.
huff

2
Bộ sưu tập Apache hiện hỗ trợ chung chung commons.apache.org/proper/commons-collections/javadocs/ mẹo
kervin

603

Nếu cấu trúc dữ liệu của bạn có ánh xạ nhiều-một giữa các khóa và giá trị, bạn nên lặp lại các mục và chọn tất cả các khóa phù hợp:

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

Trong trường hợp mối quan hệ một đối một , bạn có thể trả về khóa khớp đầu tiên:

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

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

Ngoài ra, đối với người dùng Guava, BiMap có thể hữu ích. Ví dụ:

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

3
Bạn có thể nói bất cứ điều gì về hiệu suất? Điều gì sẽ được tối ưu hóa hơn? Cái này hay BidiMap?
tasomaniac

Tôi đã nghĩ cùng một giải pháp, tất nhiên tôi đã nâng cấp nó nhưng tôi nghi ngờ về hiệu quả của nó khi nói đến Bộ sưu tập thực sự lớn.
arjacsoh

3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap có độ phức tạp về thời gian o(1). Nếu bạn lặp đi lặp lại các giá trị thì nó sẽ giết hiệu suất. Nếu bạn muốn better performancevà có một one-onemối quan hệ, bạn có thể sử dụng another mapở đâuvalue is a key
veer7

3
Tôi khuyên bạn nên thay thế .filter(entry -> entry.getValue().equals(value))bằng không có tuyên bố nào về khả năng đã được thực hiện. Hơn nữa, bạn có thể thay thế bằng.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Holger

Tôi đang gặp khó khăn trong việc hiểu ký hiệu <T, E> trước khi đặt <T> getKeysByValue () ... điểm nào .... cách khác nhau để làm điều đó mà không sử dụng? cảm ơn
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());
            }
        }
    }
}

Một số thông tin bổ sung ... Có thể hữu ích cho bạn

Phương pháp trên có thể không tốt nếu hashmap của bạn thực sự lớn. Nếu hashmap của bạn chứa khóa duy nhất để ánh xạ giá trị duy nhất, bạn có thể duy trì thêm một hashmap có chứa ánh xạ từ Giá trị sang Khóa.

Đó là bạn phải duy trì hai hashtag

1. Key to value

2. Value to key 

Trong trường hợp đó, bạn có thể sử dụng hàm băm thứ hai để lấy khóa.


19

Tôi nghĩ rằng sự lựa chọn của bạn là

  • Sử dụng triển khai bản đồ được xây dựng cho việc này, như BiMap từ các bộ sưu tập của google. Lưu ý rằng bộ sưu tập BiMap của google yêu cầu các giá trị duy nhất, cũng như các khóa, nhưng nó cung cấp hiệu suất cao trong cả hai hướng hiệu suất
  • Duy trì thủ công hai bản đồ - một cho khóa -> giá trị và một bản đồ khác cho giá trị -> khóa
  • Lặp lại thông qua entrySet()và để tìm các khóa khớp với giá trị. Đây là phương pháp chậm nhất, vì nó yêu cầu lặp qua toàn bộ bộ sưu tập, trong khi hai phương pháp khác không yêu cầu điều đó.

19

Bạn có thể chèn cả khóa, cặp giá trị và nghịch đảo của nó vào cấu trúc bản đồ của bạn

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

Sử dụng map.get ("theValue") sau đó sẽ trả về "theKey".

Đó là một cách nhanh chóng và bẩn thỉu mà tôi đã tạo ra các bản đồ không đổi, sẽ chỉ hoạt động với một vài bộ dữ liệu được chọn:

  • Chỉ chứa 1 đến 1 cặp
  • Tập hợp các giá trị tách rời khỏi bộ khóa (1-> 2, 2-> 3 phá vỡ nó)

4
Điều này không thực sự chính xác. Điều này không chỉ yêu cầu 1-1 mà còn là tập hợp các giá trị tách rời khỏi tập hợp các khóa. Bạn không thể áp dụng điều này cho bản đồ phỏng đoán {1 -> 2, 2 -> 3}: 2 vừa là giá trị vừa là khóa.
Luis A. Florit

15

Trang trí bản đồ với việc thực hiện của riêng bạn

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

Tôi nghĩ rằng đây là một cách tiếp cận thú vị, mặc dù vì mối quan hệ phải là 1: 1, tôi sẽ loại bỏ hoàn toàn HashMap và thực hiện giao diện Map <K, V> để tránh trùng lặp cả hai, giá trị và khóa.
Fran Marzoa

11

Không có câu trả lời rõ ràng, bởi vì nhiều khóa có thể ánh xạ tới cùng một giá trị. Nếu bạn đang thực thi tính độc đáo bằng mã của riêng mình, giải pháp tốt nhất là tạo một lớp sử dụng hai Hashmap để theo dõi ánh xạ theo cả hai hướng.


11

Để tìm tất cả các khóa ánh xạ tới giá trị đó, hãy lặp qua tất cả các cặp trong hàm băm, sử dụng map.entrySet().


4
Giải pháp này cực kỳ chuyên sâu, đến mức không thực tế trên các HashMaps lớn.
Joehot200

10

Sử dụng Java 8:

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

6
value=="foo" Điều này sẽ không hoạt động. equalsnên được sử dụng để so sánh Chuỗi.
Anton Balaniuc

@Anton, đúng trừ khi valueđã được thực tập.
frododot

9

Nếu bạn xây dựng bản đồ theo mã của riêng mình, hãy thử đặt khóa và giá trị trong bản đồ cùng nhau:

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

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

Sau đó, khi bạn có một giá trị, bạn cũng có chìa khóa.


3
Thông minh, nhưng nếu có 2 hoặc nhiều đối tượng KeyValue chứa cùng một giá trị thì sao? Nên chọn chìa khóa nào?
Vineet Reynold

2
@Vineet, tôi không thấy cách tiếp cận này giải quyết câu hỏi của OP. Ý của bạn là gì khi "Sau đó, khi bạn có một giá trị, bạn cũng có chìa khóa."?
Qiang Li

9

Tôi nghĩ rằng đây là giải pháp tốt nhất, địa chỉ gốc: 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;
          }
        }

Cách sử dụng dễ dàng: nếu bạn đặt tất cả dữ liệu vào hasMap và bạn có item = "Ô tô", vì vậy bạn đang tìm khóa của nó trong hashMap. đó là giải pháp tốt

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

7

Tôi sợ bạn sẽ phải lặp lại bản đồ của bạn. Ngắn nhất tôi có thể đến với:

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

Có vẻ như cách tốt nhất là bạn lặp đi lặp lại qua các mục sử dụng map.entrySet()map.containsValue()có thể thực hiện điều này bằng mọi cách.


Vâng, đó chính xác là những gì nó làm. Nhưng tất nhiên, nó trả về đúng ngay khi tìm thấy một giá trị mà .equals là đúng, trái ngược với những gì OP có thể sẽ cần phải làm.
CPerkins

1
Chà, lặp đi lặp lại qua các mục có thể trả về bằng khóa ngay khi nó cũng tìm thấy một giá trị khớp. Nhiều trận đấu dường như không phải là một mối quan tâm.
Jonas K

6

Đối với API nhắm mục tiêu phát triển Android <19, giải pháp mối quan hệ một đối một của Vitalii Fedorenko không hoạt động vì Objects.equalskhông được triển khai. Đây là một thay thế đơn giản:

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

Giải pháp này hiệu quả với tôi; đồng thời phát triển phiên bản Android khảo cổ, trong trường hợp của tôi để lấy khóa của điểm đánh dấu Google Map được giữ trong Bản đồ trong một sự kiện "onMarkerClick". Lặp lại các công việc entryset; nhưng lặp lại các khóa và khớp chúng với các mục với get () và so sánh đầu ra, thì không.
Toby Wilson

3

Bạn có thể sử dụng như sau:

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

Thật tuyệt khi bạn muốn cung cấp những thứ hữu ích, nhưng nó không nên là câu trả lời "chỉ mã" và bản thân mã cũng không nên có mùi mã.
Tom

2

Có, bạn phải lặp qua hashmap, trừ khi bạn triển khai một cái gì đó dọc theo dòng của những câu trả lời khác nhau này gợi ý. Thay vì loay hoay với entryset, tôi chỉ cần lấy keyset (), lặp lại bộ đó và giữ khóa (đầu tiên) mang lại cho bạn giá trị khớp. Nếu bạn cần tất cả các khóa phù hợp với giá trị đó, rõ ràng bạn phải làm toàn bộ.

Như Jonas gợi ý, đây có thể là những gì phương thức chứaValue đang thực hiện, vì vậy bạn có thể bỏ qua bài kiểm tra đó cùng nhau và chỉ cần lặp lại mỗi lần (hoặc có thể trình biên dịch sẽ loại bỏ sự dư thừa, ai biết được).

Ngoài ra, liên quan đến các câu trả lời khác, nếu bản đồ đảo ngược của bạn trông giống như

Map<Value, Set<Key>>

bạn có thể đối phó với ánh xạ khóa không duy nhất-> giá trị, nếu bạn cần khả năng đó (gỡ chúng sang một bên). Điều đó sẽ kết hợp tốt vào bất kỳ giải pháp nào mà mọi người đề xuất ở đây bằng cách sử dụng hai bản đồ.


2

Bạn có thể lấy khóa bằng các giá trị sử dụng mã sau ..

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

}

Tôi nghĩ rằng câu trả lời này có thể được cải thiện bằng cách thêm một lời giải thích.
Jonathan

2
-1. Tôi đã thử nó với Stringchìa khóa và giá trị. Khi tôi gọi map.add("1", "2"); map.add("1","3");thì tôi có thể gọi map.getKey("2");và lấy "1", mặc dù đó "1"là chìa khóa cho "3".
jlordo

@Jonathan ý tưởng đằng sau lớp này là giữ một HashMap khác với ánh xạ ngược để ngoài việc lấy ra một giá trị từ một khóa, bạn có thể lấy một khóa từ một giá trị. Các lớp T1 & T2 hơi khó hiểu; có thể nghĩa đen đặt tên cho chúng là Key & Value thay thế? Mặc dù tôi mong đợi khả năng nhận lại nhiều hơn một giá trị hoặc nhiều hơn một khóa, tùy thuộc vào dữ liệu & những gì bạn muốn. Sử dụng thận trọng
Chicowitz

1
@theknightwhosaysni "1" không phải là chìa khóa cho "2" (nữa). Đây cũng là câu trả lời cho câu hỏi của bạn, cuộc gọi getValue("1")sẽ trở lại 3.
jlordo

Xin lỗi jlordo, tôi đã nhầm về hành vi Hashmap tiêu chuẩn: bạn đã đúng khi thêm giá trị mới cho khóa sẽ thay thế giá trị cũ
Chicowitz

2

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

Bản đồ <Chuỗi, Số nguyên> map = new HashMap <Chuỗi, Số nguyên> (); map.put ("A", 1); map.put ("B", 2); map.put ("C", 3); map.put ("D", 4); // System.out.println (bản đồ); System.out.println (getKey (bản đồ, "4"));
Ấn Độ tuyệt vời

1
Điều gì xảy ra nếu nhiều khóa có cùng giá trị?
Cà phê Đông

Khi bạn vượt qua nhiều khóa có cùng giá trị, chúng ta sẽ nhận được khóa cuối cùng. ví dụ: Đầu ra A 1, B 1, C 1, D 2: nếu chúng ta vượt qua giá trị 1, đầu ra sẽ là C
Amazing India

@AmazedIndia Điều này không được đảm bảo và hoàn toàn phụ thuộc vào việc thực hiện bản đồ cụ thể. Ví dụ, HashMap không đảm bảo một đơn đặt hàng, vì vậy bạn không biết đầu ra nào sẽ được trả lại ở đây.
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

Sử dụng một trình bao bọc mỏng: 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 xu của tôi. Bạn có thể lấy các khóa trong một mảng và sau đó lặp qua mảng. Điều này sẽ ảnh hưởng đến hiệu suất của khối mã này nếu bản đồ khá lớn, trong đó bạn sẽ nhận được các khóa trong một mảng trước tiên có thể tiêu tốn một thời gian và sau đó bạn đang lặp. Nếu không, đối với bản đồ nhỏ hơn, nó sẽ ổn.

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

Và tại sao ai đó nên sử dụng phương pháp đó? Như bạn đã nói, hiệu suất sẽ kém hơn so với các phương pháp khác.
Tom

1

Tôi nghĩ rằng keyset () có thể tốt để tìm ánh xạ khóa tới giá trị và có kiểu mã hóa tốt hơn entryset () .

Ví dụ:

Giả sử bạn có bản đồ HashMap , độ phân giải ArrayList , giá trị bạn muốn tìm tất cả ánh xạ khóa , sau đó lưu trữ khóa vào độ phân giải .

Bạn có thể viết mã dưới đây:

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

thay vì sử dụng entryset () bên dưới:

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

Hy vọng nó giúp :)


map.get(key) == valuekhông phải là một ý tưởng tốt khi kiểm tra sự bình đẳng của các đối tượng, vì bạn đang so sánh các tài liệu tham khảo. Bình đẳng đối tượng nên luôn luôn sử dụng.equals()
frododot 14/11/18

1

Trong khi điều này không trực tiếp trả lời câu hỏi, nó có liên quan.

Bằng cách này, bạn không cần phải tiếp tục tạo / lặp. Chỉ cần tạo một bản đồ đảo ngược một lần và có được những gì bạn cầ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

Điều quan trọng cần lưu ý là vì câu hỏi này, Bộ sưu tập Apache hỗ trợ BidiMaps chung . Vì vậy, một số câu trả lời được bình chọn hàng đầu không còn chính xác ở điểm đó.

Đối với BidiMap được tuần tự hóa cũng hỗ trợ các giá trị trùng lặp (kịch bản 1-nhiều) cũng xem xét MapDB.org .


0
  1. Nếu bạn muốn lấy khóa từ giá trị, tốt nhất nên sử dụng hồ sơ dự thầu (bản đồ hai chiều), bạn có thể nhận khóa từ giá trị trong thời gian O (1).

    Nhưng, nhược điểm của việc này là bạn chỉ có thể sử dụng bộ khóa và bộ giá trị duy nhất.

  2. Có một cấu trúc dữ liệu được gọi là Bảng trong java, không có gì ngoài bản đồ của các bản đồ như

    Bảng <A, B, C> == map <A, map <B, C >>

    Ở đây bạn có thể nhận được map<B,C>bằng cách truy vấn T.row(a);và bạn cũng có thể nhận được map<A,C>bằng cách truy vấnT.column(b);

Trong trường hợp đặc biệt của bạn, chèn C là một số hằng.

Vì vậy, nó giống như <a1, b1, 1> <a2, b2, 1>, ...

Vì vậy, nếu bạn tìm thấy thông qua T.row (a1) ---> trả về bản đồ của -> lấy keyset bản đồ được trả về này.

Nếu bạn cần tìm giá trị khóa sau đó, T.column (b2) -> trả về bản đồ của -> lấy bộ khóa của bản đồ được trả về.

Ưu điểm so với trường hợp trước:

  1. Có thể sử dụng nhiều giá trị.
  2. Hiệu quả hơn khi sử dụng bộ dữ liệu lớn.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.