HashMap 設計為 Key → Value 單向映射,原生不支持按 Value 反查 Key。實際開發中常遇到「一個 Value 對應多個 Key」(如權限碼→用戶 ID)需反查場景。
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
遍歷 entrySet() | 無額外內存,代碼簡單 | O(n) 時間複雜度,頻繁查詢性能差 | 數據量小、查詢頻率低 |
維護雙向 Map (Guava BiMap 或兩個 Map) | O(1) 查詢 | 雙倍內存,插入刪除需同步維護 | 頻繁雙向查詢、數據量中等 |
MultiMap (Guava ArrayListMultimap) | 原生支持一鍵多值 | 引入第三方依賴 | 一對多映射、需刪除單個映射 |
值唯一時用 BiMap | 強制 1:1,自動反向索引 | 值重複會拋異常 | 業務保證 Value 唯一 |
import java.util.*;
public class MapValueGetKey {
/**
* 根據 value 反查所有匹配的 key
* @param map 目標 Map
* @param value 待查值
* @param <K> Key 類型
* @param <V> Value 類型
* @return 匹配的 key 列表,無匹配返回空列表
*/
public static <K, V> List<K> getKeysByValue(Map<K, V> map, V value) {
List<K> keys = new ArrayList<>();
if (map == null || value == null) return keys;
for (Map.Entry<K, V> entry : map.entrySet()) {
if (Objects.equals(entry.getValue(), value)) {
keys.add(entry.getKey());
}
}
return keys;
}
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "A");
map.put(3, "B");
map.put(4, "A");
map.put(5, "C");
String target = "A";
List<Integer> keys = getKeysByValue(map, target);
System.out.println("Value '" + target + "' 對應的 Keys: " + keys);
// 輸出: [1, 2, 4]
}
}
若系統高頻反查,建議封裝雙 Map 結構:
public class BiHashMap<K, V> {
private final Map<K, V> keyToValue = new HashMap<>();
private final Map<V, Set<K>> valueToKeys = new HashMap<>();
public void put(K key, V value) {
// 移除舊映射
V oldVal = keyToValue.get(key);
if (oldVal != null) {
Set<K> set = valueToKeys.get(oldVal);
if (set != null) set.remove(key);
}
// 建立新映射
keyToValue.put(key, value);
valueToKeys.computeIfAbsent(value, k -> ConcurrentHashMap.newKeySet()).add(key);
}
public V get(K key) { return keyToValue.get(key); }
public Set<K> getKeys(V value) {
return valueToKeys.getOrDefault(value, Collections.emptySet());
}
public void remove(K key) {
V val = keyToValue.remove(key);
if (val != null) {
Set<K> set = valueToKeys.get(val);
if (set != null) set.remove(key);
}
}
}
HashMap 允許一個 null key、多個 null value,反查時需用 Objects.equals 防 NPE。ConcurrentHashMap + 上述雙 Map 邏輯,或直接用 Guava Multimap 的線程安全實現。equals 和 hashCode,否則反查失效。偶爾反查用 entrySet() 遍歷最簡潔;高頻雙向查詢請自維護雙 Map 或引入 Guava Multimap/BiMap。選型核心:查詢頻率 vs 內存開銷 vs 維護成本。