有关Java中集合的知识

Java Map 集合完整知识点

一、Map 基础概述

1. 存储结构: java.util.Map<K,V>  是键值对(Key-Value)双列集合, K  键、 V  值,键唯一,值可重复
2. 特点

  • 键(Key):不可重复,一个键只能对应一个值
  • 值(Value):可重复,多个键可以映射同一个值
  • 一个键值对是一个 Entry 对象,Map底层存放 Entry
  • 无序(部分实现类有序),没有索引,不能用普通for循环遍历
    3. 与Collection区别:Collection是单列集合(只存一个元素),Map双列(一对元素)

二、常用实现类对比

实现类 底层结构 键是否允许null 有序性 线程安全 适用场景
HashMap 数组+链表+红黑树 键最多一个null,值任意null 无序 不安全,效率最高 绝大多数日常开发,查询增删快
LinkedHashMap HashMap+双向链表 同HashMap 插入顺序有序 不安全 需要保留存入顺序的场景
TreeMap 红黑树 不允许null键 按键自然排序/自定义排序 不安全 需要对key自动排序
Hashtable 数组+链表 键和值都不允许null 无序 安全,加synchronized 基本淘汰,遗留老代码
Properties 继承Hashtable 键值只能是String 无序 安全 读取配置文件xxx.properties

核心类重点讲解

  1. HashMap(最常用)
  • JDK1.8优化:链表长度>8且数组长度≥64,转为红黑树;红黑树节点<6转回链表
  • 默认初始容量 16 ,负载因子 0.75 :元素个数 > 容量*0.75 自动扩容为2倍
  • 键的自定义类:必须重写hashCode()和equals(),保证相同对象哈希值相等、equals相等
  1. LinkedHashMap

继承HashMap,额外维护双向链表记录插入顺序,遍历顺序=存入顺序
可以构造访问顺序模式(LRU缓存底层)

  1. TreeMap

key必须实现 Comparable 接口,或创建TreeMap时传入 Comparator 比较器
自动按照key升序/自定义规则排序

三、Map 常用API方法

  1. 添加/修改

java

V put(K key, V value)
// 键不存在:新增,返回null;键已存在:覆盖旧值,返回被覆盖的旧值

void putAll(Map<? extends K,? extends V> m) // 批量导入另一个map

  1. 删除

java

V remove(Object key) // 根据键删除,返回被删除的值
boolean remove(Object key, Object value) // 键值匹配才删除
void clear() // 清空所有元素

  1. 查询/判断

java

V get(Object key) // 根据key取值,不存在返回null
V getOrDefault(K key, V defaultValue) // 不存在返回默认值(推荐)

boolean containsKey(Object key) // 是否包含某个键
boolean containsValue(Object value) // 是否包含某个值

int size() // 获取键值对数量
boolean isEmpty() // 判断是否为空

  1. 集合视图(遍历必备)

java

Set keySet() // 获取所有key的Set集合
Collection values() // 获取所有value的集合
Set<Map.Entry<K,V>> entrySet() // 获取所有键值对对象Entry的Set

四、Map 四种遍历方式

java

HashMap<String, Integer> map = new HashMap<>();
map.put("张三", 20);
map.put("李四", 22);

方式1:keySet() 先遍历key,再get取值(常用)

java

Set keys = map.keySet();
for (String key : keys) {
Integer val = map.get(key);
System.out.println(key + "=" + val);
}

方式2:entrySet() 获取键值对(效率最高,大数据优先)

java

Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
Integer val = entry.getValue();
}

方式3:forEach Lambda(简洁,JDK8+)

java

map.forEach((k, v) -> System.out.println(k + ":" + v));

方式4:迭代器遍历

java

Iterator<Map.Entry<String,Integer>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,Integer> e = it.next();
}

五、JDK8 新增常用方法

1.  computeIfAbsent(key, 函数) :key不存在才计算赋值,存在不改动
2.  computeIfPresent(key, 函数) :key存在才修改value
3.  merge(key, newValue, 合并函数) :不存在就存入,存在则新旧值合并

示例:统计字符串字符出现次数

java

String s = "aabbbcc";
HashMap<Character, Integer> count = new HashMap<>();
for (char c : s.toCharArray()) {
count.merge(c, 1, Integer::sum);
}

六、使用注意事项

1. HashMap键自定义类必须重写hashCode+equals
只重写equals不重写hashCode:两个相等对象哈希值不同,会存成两个键
2. 多线程环境不要用HashMap,并发扩容会死循环、数据丢失
线程安全替代: ConcurrentHashMap (高并发首选,分段锁,性能远优于Hashtable)
3. TreeMap的key不能为null,且必须具备比较规则
4. 尽量使用 getOrDefault 代替get,避免null空指针

posted @ 2026-06-14 21:43  李伯韬  阅读(9)  评论(0)    收藏  举报