Java HashMap
                           
天天向上
发布: 2025-03-02 18:43:49

原创
781 人浏览过

HashMap 是 Java 集合框架中实现了 Map 接口的一个类,它基于哈希表(HashTable)实现,用来存储键值对(key-value)。在 HashMap 中,键(key)是唯一的,而值(value)可以重复。HashMap 提供了高效的查找、插入和删除操作,通常用于需要根据键快速查找值的场景。

1. HashMap 的基本特性

  • 基于哈希表实现HashMap 使用哈希表来存储数据,它利用键的 hashCode() 方法来决定元素存储的桶位置。
  • 键的唯一性HashMap 中的每个键(key)是唯一的。如果向 HashMap 中插入一个已存在的键,则新的值会替换掉原有的值。
  • 允许 null 值和 nullHashMap 允许一个 null 键和多个 null 值。
  • 无序性HashMap 中的元素没有固定的顺序,元素的顺序依赖于其哈希值。
  • 线程不安全HashMap 本身是非线程安全的,多个线程同时访问和修改 HashMap 可能会导致数据不一致。

2. HashMap 的常用构造函数

// 默认构造函数,创建一个空的 HashMap,默认初始容量为 16,负载因子为 0.75
HashMap<K, V> map = new HashMap<>();

// 使用指定的初始容量构造 HashMap
HashMap<K, V> map = new HashMap<>(int initialCapacity);

// 使用指定的初始容量和负载因子构造 HashMap
HashMap<K, V> map = new HashMap<>(int initialCapacity, float loadFactor);

// 基于另一个 Map 创建 HashMap
HashMap<K, V> map = new HashMap<>(Map<? extends K, ? extends V> m);

3. HashMap 常用方法

3.1 添加元素

  • put(K key, V value):将指定的键值对插入 HashMap 中。如果键已经存在,则更新其对应的值。
map.put("Apple", 1);  // 添加键值对
map.put("Banana", 2); // 添加键值对
map.put("Apple", 3);  // 更新 "Apple" 的值为 3

3.2 删除元素

  • remove(Object key):根据指定的键删除键值对,返回被删除的值。如果键不存在,返回 null
map.remove("Apple");  // 删除 "Apple" 键的对应值

3.3 查询元素

  • get(Object key):根据指定的键获取对应的值,如果键不存在则返回 null
int value = map.get("Apple"); // 返回 "Apple" 对应的值
  • containsKey(Object key):检查 HashMap 是否包含指定的键。
boolean contains = map.containsKey("Banana"); // 判断是否包含键 "Banana"
  • containsValue(Object value):检查 HashMap 是否包含指定的值。
boolean containsValue = map.containsValue(3); // 判断是否包含值 3

3.4 修改元素

  • replace(K key, V value):如果键存在,则更新其对应的值并返回旧值;如果键不存在,则返回 null
map.replace("Banana", 5);  // 更新 "Banana" 的值为 5
  • replace(K key, V oldValue, V newValue):仅在值等于 oldValue 时,才会替换为 newValue,返回 truefalse
boolean replaced = map.replace("Banana", 2, 5); // 仅在值为 2 时,替换为 5

3.5 其他常用方法

  • size():返回 HashMap 中的键值对数。
int size = map.size(); // 获取元素个数
  • isEmpty():判断 HashMap 是否为空。
boolean empty = map.isEmpty(); // 判断是否为空
  • clear():清空 HashMap 中的所有键值对。
map.clear(); // 清空所有元素
  • keySet():返回 HashMap 中所有键的集合。
Set<K> keys = map.keySet();  // 获取所有键
  • values():返回 HashMap 中所有值的集合。
Collection<V> values = map.values();  // 获取所有值
  • entrySet():返回 HashMap 中所有键值对的 Set 集合,使用 Map.Entry 对象。
Set<Map.Entry<K, V>> entrySet = map.entrySet();  // 获取所有键值对

3.6 遍历 HashMap

  • 使用 for-each 循环:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}
  • 使用 Iterator
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Integer> entry = iterator.next();
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

3.7 默认值处理

  • getOrDefault(Object key, V defaultValue):如果指定的键存在,则返回对应的值,否则返回 defaultValue
int value = map.getOrDefault("Apple", 0); // 如果 "Apple" 存在,则返回其值,否则返回 0

4. HashMap 的性能

  • 查找、插入、删除HashMap 的常规操作(如查找、插入、删除)时间复杂度是 O(1),但如果发生哈希冲突,操作时间复杂度可能会退化为 O(n)。
  • 负载因子和容量HashMap 的性能受初始容量和负载因子的影响。负载因子是一个衡量哈希表“满”程度的参数,默认值为 0.75。负载因子较大时会减少扩容的次数,但会增加哈希冲突的概率。
  • 扩容时会将容量翻倍,并重新计算每个元素的哈希值。
  • 选择适当的负载因子可以有效平衡时间复杂度和空间复杂度。

5. HashMap 与其他 Map 的比较

特性HashMapTreeMapLinkedHashMap
底层实现哈希表红黑树哈希表 + 双向链表
键值对顺序无序有序(按自然顺序或自定义顺序)按插入顺序或访问顺序有序
性能O(1)(查找、插入、删除)O(log n)(查找、插入、删除)O(1)(查找、插入、删除)
是否允许 null 键/值允许 1 个 null 键和多个 null 值不允许 null 键允许 1 个 null 键和多个 null 值

6. 线程安全

HashMap 不是线程安全的。如果多个线程同时访问 HashMap,可能会导致数据不一致。如果需要线程安全的实现,可以使用以下方法:

  • 使用 Collections.synchronizedMap()HashMap 包装为线程安全的 Map
  • 使用 ConcurrentHashMap,它是线程安全的,并且支持更高的并发性能,适用于多线程环境。
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());

7. 使用 HashMap 的场景

HashMap 适合用于以下场景:

  • 快速查找和更新数据:如果需要根据某个唯一的键快速查找、更新或删除数据,HashMap 是一个很好的选择。
  • 去重操作:可以用 HashMap 来判断一个元素是否出现过,如果 key 存在,表示已经出现过,否则表示第一次出现。
  • 实现缓存:当需要根据键快速查找缓存中的数据时,HashMap 是一种理想的选择。

小结

HashMap 是一个高效的键值对存储容器,适用于需要根据键快速查找、插入或删除数据的场景。更多详细内容请关注其他相关文章。

发表回复 0

Your email address will not be published. Required fields are marked *