Java中Map的全面概念解析

Map 是 Java 集合框架中键值对(Key-Value Pair)的存储容器,核心特征是键的唯一性——一个键只能映射到一个值,新值会覆盖同键的旧值,它与 Collection 接口是并列的顶级集合类型,不继承 Collection。

一、核心特性

1. 键的唯一性:键(Key)必须重写  hashCode()  和  equals()  方法来保证唯一性,值(Value)可以重复。

2. 无序/有序特性:不同实现类对元素的存储顺序不同,如 HashMap 无序,TreeMap 按键排序,LinkedHashMap 按插入顺序保存。

3. 允许 null 值:HashMap、LinkedHashMap 允许键和值为 null(键只能有一个 null),TreeMap 不允许键为 null,Hashtable 则键和值都不允许 null。

4. 线程安全:Hashtable 是线程安全的(方法加了  synchronized ),HashMap 是线程不安全的;并发场景下推荐使用  ConcurrentHashMap ,它的并发性能优于 Hashtable。

 

二、核心接口方法

 

Map 接口定义了操作键值对的核心方法,常用的有:

 

-  V put(K key, V value) :将键值对存入 Map,若键已存在则覆盖旧值并返回旧值,否则返回 null。

-  V get(Object key) :根据键获取对应的值,键不存在则返回 null。

-  V remove(Object key) :删除指定键的键值对,返回被删除的值。

-  boolean containsKey(Object key) :判断 Map 中是否包含指定键。

-  boolean containsValue(Object value) :判断 Map 中是否包含指定值。

-  Set<K> keySet() :返回 Map 中所有键的 Set 集合。

-  Collection<V> values() :返回 Map 中所有值的 Collection 集合。

-  Set<Map.Entry<K,V>> entrySet() :返回 Map 中所有键值对( Map.Entry  对象)的 Set 集合,是遍历 Map 的高效方式。

-  void clear() :清空 Map 中的所有键值对。

-  int size() :返回 Map 中键值对的数量。

 

三、Map.Entry 内部接口

 

 Map.Entry<K,V>  是 Map 的静态内部接口,用于表示一个键值对对象,提供了操作单个键值对的方法:

 

-  K getKey() :获取当前键值对的键。

-  V getValue() :获取当前键值对的值。

-  V setValue(V value) :修改当前键值对的值,返回旧值。

 

四、常见实现类

 

1. HashMap

- 底层实现:基于哈希表(数组+链表/红黑树),JDK 1.8 后当链表长度超过阈值(默认 8)且数组长度≥64 时,链表转为红黑树以提升查询效率。

- 特点:无序存储,查询、插入、删除效率高(平均时间复杂度 O(1)),线程不安全,允许键和值为 null。

- 适用场景:非并发场景下的常规键值对存储,是最常用的 Map 实现类。

2. LinkedHashMap

- 底层实现:基于哈希表+双向链表,继承自 HashMap。

- 特点:按插入顺序或访问顺序保存键值对,查询效率略低于 HashMap,线程不安全,允许键和值为 null。

- 适用场景:需要保持键值对插入顺序或访问顺序的场景(如 LRU 缓存的基础实现)。

3. TreeMap

- 底层实现:基于红黑树。

- 特点:按键的自然顺序或**自定义比较器(Comparator)**排序,查询、插入、删除时间复杂度 O(log n),线程不安全,键不允许为 null。

- 适用场景:需要对键进行排序的场景。

4. Hashtable

- 底层实现:基于哈希表,是 JDK 早期的 Map 实现类。

- 特点:线程安全(方法加锁),但并发性能低,键和值都不允许为 null,无序存储。

- 适用场景:已被  ConcurrentHashMap  替代,仅用于兼容旧代码。

5. ConcurrentHashMap

- 底层实现:JDK 1.7 基于分段锁,JDK 1.8 基于哈希表+红黑树+CAS 机制,取消了分段锁。

- 特点:线程安全,并发性能高(支持多线程同时操作不同的桶),键和值都不允许为 null。

- 适用场景:高并发环境下的键值对存储。

 

五、遍历方式

 

Map 有三种常见的遍历方式,效率从高到低排序为: entrySet()  >  keySet()  >  values() (仅遍历值)

 

1. 通过 entrySet 遍历(推荐,高效)

直接获取所有键值对对象,一次遍历即可获取键和值。

2. 通过 keySet 遍历

先获取所有键的集合,再通过键获取对应的值,会额外触发  get()  方法的哈希查询。

3. 通过 values 遍历

仅遍历所有值,无法获取对应的键。

 

六、使用注意事项

 

1. 键的 hashCode() 和 equals() 重写

自定义对象作为键时,必须重写这两个方法,否则会导致键的唯一性判断失效(如 HashMap 中出现重复键)。

2. 线程安全问题

多线程环境下,避免使用 HashMap,优先选择  ConcurrentHashMap ;不要在遍历 Map 时进行增删操作,否则会抛出  ConcurrentModificationException ,可通过迭代器的  remove()  方法或使用并发集合解决。

3. 初始容量和负载因子

HashMap 的默认初始容量是 16,负载因子是 0.75;当元素数量达到  容量×负载因子  时,会触发扩容(重新哈希),频繁扩容会影响性能,可根据预期存储数量设置合适的初始容量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值