HashMap 是 Java 集合框架中的一个重要类,属于 java.util 包。它是基于哈希表(Hash Table)实现的,提供了键值对(key-value pair)的存储方式。HashMap 允许使用 null 作为键或值,并且不保证元素的顺序。
主要特点
键值对存储:HashMap 以键值对(key-value pair)的形式存储数据。
允许 null 键和值:HashMap 允许一个 null 键和多个 null 值。
无序集合:HashMap 不保证元素的顺序。
非线程安全:HashMap 不是线程安全的,如果需要在多线程环境中使用,请考虑使用 Collections.synchronizedMap 或者 ConcurrentHashMap。
构造方法
HashMap():构造一个默认初始容量为 16、加载因子为 0.75 的空 HashMap。
HashMap(int initialCapacity):构造一个具有指定初始容量、默认加载因子的空 HashMap。
HashMap(int initialCapacity, float loadFactor):构造一个具有指定初始容量和加载因子的空 HashMap。
HashMap(Map<? extends K, ? extends V> m):构造一个新的 HashMap,其包含指定映射的映射关系。
主要方法
插入操作:
V put(K key, V value):将指定的值与此映射中的指定键关联。如果映射先前包含一个该键的映射,则返回旧值,否则返回 null。
删除操作:
V remove(Object key):如果存在一个键的映射关系,则将其从映射中移除,并返回该键的旧值。
访问操作:
V get(Object key):返回到指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
boolean containsKey(Object key):如果此映射包含对于指定键的映射关系,则返回 true。
boolean containsValue(Object value):如果此映射为指定值映射一个或多个键,则返回 true。
其他操作:
void clear():从该映射中移除所有映射关系。
int size():返回此映射中的键-值映射关系数。
Set<K> keySet():返回此映射中包含的键的 Set 视图。
Collection<V> values():返回此映射中包含的值的 Collection 视图。
Set<Map.Entry<K, V>> entrySet():返回此映射中包含的映射关系的 Set 视图。
使用示例
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// 创建一个 HashMap
Map<String, Integer> hashMap = new HashMap<>();
// 插入键值对
hashMap.put("Apple", 1);
hashMap.put("Banana", 2);
hashMap.put("Orange", 3);
// 获取值
Integer appleCount = hashMap.get("Apple");
System.out.println("Apple: " + appleCount); // 输出:Apple: 1
// 检查键是否存在
boolean hasBanana = hashMap.containsKey("Banana");
System.out.println("Contains Banana: " + hasBanana); // 输出:Contains Banana: true
// 移除键值对
Integer removedValue = hashMap.remove("Orange");
System.out.println("Removed Orange value: " + removedValue); // 输出:Removed Orange value: 3
// 遍历 HashMap
System.out.println("HashMap elements:");
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 清空 HashMap
hashMap.clear();
System.out.println("Size after clearing: " + hashMap.size()); // 输出:Size after clearing: 0
}
}
内部工作原理
HashMap 内部通过数组和链表(Java 8 之后使用红黑树优化)相结合的方式来处理哈希冲突。具体步骤如下:
计算哈希值:调用键的 hashCode() 方法,计算出键的哈希值。
索引计算:根据哈希值计算出在数组中的索引位置。
java
int index = (n - 1) & hash;
处理冲突:如果在该索引位置已经有一个或多个键值对(即哈希冲突),则通过链表(或红黑树)将新的键值对链接起来。
调整大小:当实际装载的元素数量超过阈值(initial capacity * load factor)时,HashMap 会进行扩容并重新散列。
扩展阅读
线程安全版本:对于线程安全的需求,可以使用 ConcurrentHashMap 代替 HashMap。
迭代顺序:如果需要按插入顺序迭代,可以使用 LinkedHashMap。
总结
HashMap 是一种高效、灵活的键值对存储结构,适用于大多数情况下的快速查找和更新操作。但要注意的是,它不是线程安全的,需要在多线程环境下特别处理。了解 HashMap 的内部工作原理和常见用法,有助于更好地运用这一强大的工具。