杰瑞科技汇

Java map key取值有哪些高效方法?

get(key)

最直接、最常用的方法是 Map 接口提供的 get(key) 方法。

Java map key取值有哪些高效方法?-图1
(图片来源网络,侵删)
import java.util.HashMap;
import java.util.Map;
public class MapGetExample {
    public static void main(String[] args) {
        // 1. 创建一个 Map 并存入数据
        Map<String, Integer> studentScores = new HashMap<>();
        studentScores.put("Alice", 95);
        studentScores.put("Bob", 88);
        studentScores.put("Charlie", 76);
        // 2. 使用 get(key) 方法获取 value
        String keyToFind = "Alice";
        Integer score = studentScores.get(keyToFind); // key 是 "Alice", value 是 95
        System.out.println("Student " + keyToFind + "'s score is: " + score); // 输出: Student Alice's score is: 95
        // 3. 尝试获取一个不存在的 key
        String nonExistentKey = "David";
        Integer nonExistentScore = studentScores.get(nonExistentKey);
        System.out.println("Student " + nonExistentKey + "'s score is: " + nonExistentScore); // 输出: Student David's score is: null
    }
}

重要细节与注意事项

处理不存在的 Key

get(key) 方法在 key 不存在时,会返回 null,这可能会引发 NullPointerException,如果你直接使用返回的值。

反例:

Map<String, Integer> map = new HashMap<>();
map.put("key1", 100);
// "key2" 不存在,get() 返回 null,调用 intValue() 会抛出 NPE
int value = map.get("key2").intValue(); // 抛出 NullPointerException

解决方案:

有几种安全的方式来处理 key 不存在的情况:

Java map key取值有哪些高效方法?-图2
(图片来源网络,侵删)

a) 使用 containsKey(key) 进行预检查

这是最传统、最安全的方式。

Map<String, Integer> map = new HashMap<>();
map.put("key1", 100);
String key = "key2";
if (map.containsKey(key)) {
    int value = map.get(key);
    System.out.println("Value: " + value);
} else {
    System.out.println("Key '" + key + "' not found.");
}

b) 使用 Java 8 的 getOrDefault(key, defaultValue) (推荐)

这个方法非常优雅,key 不存在,则返回你指定的默认值,而不是 null

Java map key取值有哪些高效方法?-图3
(图片来源网络,侵删)
Map<String, Integer> map = new HashMap<>();
map.put("key1", 100);
// key 不存在,返回默认值 0
int value = map.getOrDefault("key2", 0);
System.out.println("Value: " + value); // 输出: Value: 0

c) 使用 Java 8 的 computeIfAbsent(key, mappingFunction) (适用于计算默认值)

当你需要为不存在的 key 计算一个默认值(而不是使用一个固定的常量)时,这个方法非常高效且线程安全(在 ConcurrentHashMap 中)。

Map<String, Integer> map = new HashMap<>();
map.put("key1", 100);
// key "key2" 不存在,则使用函数 () -> 0 * 10 来计算其值
// 并且将计算结果存入 map
int value = map.computeIfAbsent("key2", k -> 0 * 10);
System.out.println("Map: " + map);      // 输出: Map: {key1=100, key2=0}
System.out.println("Value: " + value); // 输出: Value: 0

处理 null Key 和 null Value

HashMap 是允许 keyvaluenull 的。

  • keynull: HashMap 内部有一个专门的位置来存储 keynull 的条目。
  • valuenull: 这是完全合法的,表示该 key 存在,但其关联的值为空。

示例:

Map<String, String> map = new HashMap<>();
map.put("name", "Alice");
map.put("address", null); // 允许 value 为 null
map.put(null, "Unknown"); // 允许 key 为 null
System.out.println(map.get("name"));      // 输出: Alice
System.out.println(map.get("address"));   // 输出: null
System.out.println(map.get(null));       // 输出: Unknown
// 当你不确定 key 是否为 null 时,get(null) 仍然可以工作
String valueForNullKey = map.get(null);
System.out.println("Value for null key: " + valueForNullKey);

重要提示: 因为 get(key)key 不存在和 value 存在但为 null 时都返回 null,所以如果你需要区分这两种情况,必须使用 containsKey(key)

Map<String, String> map = new HashMap<>();
map.put("key1", null);
// 无法区分 "key1" 不存在还是 "key1" 的值是 null
String value = map.get("key1"); // value 是 null
// 使用 containsKey 来区分
if (map.containsKey("key1")) {
    System.out.println("The key 'key1' exists, its value is null.");
} else {
    System.out.println("The key 'key1' does not exist.");
}

不同 Map 实现类的 get 方法行为

get(key)Map 接口的方法,所以所有 Map 的实现类(如 HashMap, TreeMap, LinkedHashMap, Hashtable)都有这个方法,但底层实现和性能有所不同。

实现类 特点 get(key) 性能 备注
HashMap 基于哈希表,无序,允许 null 键和值。 平均 O(1),最坏情况 O(n)(哈希冲突严重时)。 最常用,适用于绝大多数场景。
TreeMap 基于红黑树,按 key 的自然排序或自定义排序规则排序。 O(log n) 当你需要对 key 进行排序或范围查找时使用。
LinkedHashMap 继承自 HashMap,同时维护了一个双向链表,记录了插入顺序或访问顺序。 平均 O(1) 当你需要保持插入顺序或访问顺序时使用。
Hashtable 基于哈希表,是遗留类。不允许 null 键和值,是线程安全的。 平均 O(1) 已被 ConcurrentHashMapHashMap 取代,除非在非常老的代码中,否则不推荐使用。
ConcurrentHashMap 高效的线程安全 Map 平均 O(1) 在多线程环境下,推荐使用它代替 Hashtable 或对 HashMapsynchronized

总结与最佳实践

  1. 基本取值: 使用 map.get(key)
  2. 避免 NullPointerException:
    • value 是基本类型(如 int),必须先检查 key 是否存在或使用 getOrDefault
    • value 是包装类型(如 Integer),null 是一个合法的值,那么直接使用 get 的结果是安全的。
  3. 推荐使用 getOrDefault: 当你希望 key 不存在时返回一个非 null 的默认值时,getOrDefault 是最简洁、最现代的选择。
  4. 需要计算默认值时使用 computeIfAbsent: 这是一个功能强大的原子操作,可以避免重复计算,并且在并发环境下表现良好。
  5. 需要区分“键不存在”和“值为 null”: 使用 map.containsKey(key) 进行判断。
  6. 选择合适的 Map 实现:
    • 默认选择 HashMap: 速度快,功能全面。
    • 需要排序 -> TreeMap
    • 需要保持顺序 -> LinkedHashMap
    • 多线程环境 -> ConcurrentHashMap
分享:
扫描分享到社交APP
上一篇
下一篇