HashMap<K, V>
HashMap<K, V>
是 Java 集合框架中用于存储键值对的重要类,它位于 java.util
包下,实现了 Map<K, V>
接口。下面从多个方面为你详细介绍 HashMap<K, V>
。
特性
- 键值对存储:
HashMap
以键值对(key - value
)的形式存储数据,每个键都是唯一的,键可以为null
,但只能有一个null
键,值可以有多个null
。 - 无序性:不保证键值对的存储顺序,即插入的顺序和遍历的顺序可能不同。
- 基于哈希表实现:利用哈希函数将键映射到哈希表的特定位置,从而实现快速的插入、删除和查找操作。
- 非线程安全:在多线程环境下,如果多个线程同时访问并修改
HashMap
,可能会导致数据不一致或抛出异常。
构造方法
HashMap()
:创建一个默认初始容量为 16,负载因子为 0.75 的空HashMap
。
import java.util.HashMap; public class HashMapExample { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); } }
HashMap(int initialCapacity)
:创建一个指定初始容量,负载因子为 0.75 的空HashMap
。
HashMap<String, Integer> map = new HashMap<>(32);
HashMap(int initialCapacity, float loadFactor)
:创建一个指定初始容量和负载因子的空HashMap
。
HashMap<String, Integer> map = new HashMap<>(32, 0.8f);
HashMap(Map<? extends K, ? extends V> m)
:创建一个包含指定Map
中所有键值对的HashMap
。
import java.util.HashMap; import java.util.Map; public class HashMapExample { public static void main(String[] args) { Map<String, Integer> anotherMap = new HashMap<>(); anotherMap.put("apple", 1); HashMap<String, Integer> map = new HashMap<>(anotherMap); } }
常用方法
- 插入和更新操作put(K key, V value):将指定的键值对插入到 HashMap 中。如果键已经存在,则更新该键对应的值。返回该键之前关联的值,如果键不存在则返回 null。
HashMap<String, Integer> map = new HashMap<>(); Integer oldValue = map.put("apple", 1);
- **`putAll(Map<? extends K, ? extends V> m)`**:将指定 `Map` 中的所有键值对复制到当前 `HashMap` 中。
Map<String, Integer> anotherMap = new HashMap<>(); anotherMap.put("banana", 2); map.putAll(anotherMap);
- 删除操作remove(Object key):从 HashMap 中移除指定键对应的键值对。返回该键关联的值,如果键不存在则返回 null。
Integer removedValue = map.remove("apple");
- 查询操作get(Object key):返回指定键关联的值,如果键不存在则返回 null。
Integer value = map.get("apple");
- **`containsKey(Object key)`**:判断 `HashMap` 中是否包含指定的键,包含返回 `true`,否则返回 `false`。
boolean hasKey = map.containsKey("apple");
- **`containsValue(Object value)`**:判断 `HashMap` 中是否包含指定的值,包含返回 `true`,否则返回 `false`。
boolean hasValue = map.containsValue(1);
- **`size()`**:返回 `HashMap` 中键值对的数量。
int size = map.size();
- 遍历操作keySet():返回一个包含 HashMap 中所有键的 Set 视图。可以通过遍历该 Set 来访问 HashMap 中的键和对应的值。
import java.util.HashMap; import java.util.Map; import java.util.Set; HashMap<String, Integer> map = new HashMap<>(); map.put("apple", 1); map.put("banana", 2); Set<String> keySet = map.keySet(); for (String key : keySet) { Integer value = map.get(key); System.out.println(key + ": " + value); }
- **`values()`**:返回一个包含 `HashMap` 中所有值的 `Collection` 视图。
import java.util.Collection; Collection<Integer> values = map.values(); for (Integer value : values) { System.out.println(value); }
- **`entrySet()`**:返回一个包含 `HashMap` 中所有键值对的 `Set` 视图,每个键值对用 `Map.Entry<K, V>` 对象表示。这种方式是最常用的遍历 `HashMap` 的方式,因为它可以同时访问键和值,并且效率较高。
import java.util.Map.Entry; Set<Entry<String, Integer>> entrySet = map.entrySet(); for (Entry<String, Integer> entry : entrySet) { String key = entry.getKey(); Integer value = entry.getValue(); System.out.println(key + ": " + value); }
注意事项
- 哈希冲突:当不同的键通过哈希函数计算得到相同的哈希值时,会发生哈希冲突。
HashMap
使用链表或红黑树来解决哈希冲突。当链表长度超过 8 且数组长度大于 64 时,链表会转换为红黑树,以提高查找效率。 - 负载因子和扩容:负载因子(默认为 0.75)表示哈希表在达到多满时进行扩容。当哈希表中的键值对数量超过
容量 * 负载因子
时,会进行扩容操作,将哈希表的容量扩大为原来的 2 倍,并重新计算所有键的哈希位置。 - 线程安全问题:如果需要在多线程环境下使用,可以考虑使用
ConcurrentHashMap
或通过Collections.synchronizedMap
方法将HashMap
包装成线程安全的Map
。
import java.util.Collections; import java.util.HashMap; import java.util.Map; Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
综上所述,HashMap
是一个非常实用的集合类,适合在大多数需要存储键值对的场景中使用,但在多线程环境下需要注意线程安全问题。
Java集合框架 文章被收录于专栏
Java集合框架是Java提供的一组用于存储和操作数据的类和接口,它位于java.util包中,为开发者提供了强大且灵活的数据存储和处理能力。以下将从整体架构、主要接口、常用实现类、使用场景以及示例代码等方面详细介绍Java集合框架。