Map接口
1. Key 必须重写 hashCode() 和 equals():尤其是自定义对象作为 Key 时,否则会导致 Key 重复、查询不到 Value(HashMap/LinkedHashMap 必做,TreeMap 可因排序省略,但建议统一重写)。• V get(Object key):通过 Key 获取 Value,Key 不存在返回 null(注意:Value 本身为 null 时无法区分“K
一、Map 核心定义
• 顶层双值集合接口,存储 Key-Value 键值对,无继承 Collection 接口,属集合框架顶层同级核心组件。
• 核心约束:Key 唯一(重复添加会覆盖旧 Value)、Value 可重复;Key/Value 均可为 null(不同实现类对 null 支持不同)。
• 核心作用:通过唯一 Key 快速定位 Value,适合“映射查询”场景(如配置存储、数据字典)。
二、Map 核心接口方法
1. 增/改操作
• V put(K key, V value):添加键值对,Key 存在则覆盖旧 Value,返回旧 Value;不存在返回 null。
• void putAll(Map<? extends K, ? extends V> m):批量添加另一个 Map 的所有键值对。
• V putIfAbsent(K key, V value):仅当 Key 不存在时添加,避免覆盖。
2. 查操作
• V get(Object key):通过 Key 获取 Value,Key 不存在返回 null(注意:Value 本身为 null 时无法区分“Key 不存在”和“Value 是 null”,需配合 containsKey 验证)。
• boolean containsKey(Object key):判断是否包含指定 Key(依赖 Key 的 hashCode() 和 equals())。
• boolean containsValue(Object value):判断是否包含指定 Value(遍历所有 Value,效率低于 containsKey)。
• int size():返回键值对的数量。
• boolean isEmpty():判断 Map 是否为空。
3. 删操作
• V remove(Object key):通过 Key 删除键值对,返回被删除的 Value;Key 不存在返回 null。
• boolean remove(Object key, Object value):仅当 Key 对应 Value 匹配时才删除,返回删除是否成功(JDK8+)。
• void clear():清空所有键值对。
4. 遍历/视图操作(核心重点)
• Set<K> keySet():返回 Key 的集合(视图,修改会同步影响原 Map),用于遍历所有 Key。
• Collection<V> values():返回 Value 的集合(视图),用于遍历所有 Value(关联 Collection 体系的唯一方式)。
• Set<Map.Entry<K, V>> entrySet():返回键值对 Entry 的集合(视图),直接遍历键值对,效率最高(优先使用)。
三、Map 核心实现类(4大主流,重点掌握)
1. HashMap(主流首选,非线程安全)
核心特性
• 排序:无序(按 Key 的哈希值存储)。
• null 支持:Key 可存 1 个 null,Value 可存多个 null。
• 效率:增删查平均 O(1),哈希冲突时退化为 O(n)(红黑树优化后 O(logn))。
• 关键参数:初始容量 16,负载因子 0.75(容量达 16×0.75=12 时扩容为 32,翻倍扩容)。
• 适用场景:单线程环境下的通用映射场景(90% 业务首选)。
注意点
• 非线程安全,多线程并发修改会触发 ConcurrentModificationException(快速失败)。
• Key 需重写 hashCode() 和 equals():保证哈希值一致时对象相等,避免 Key 重复或查询失效。
2. LinkedHashMap(有序 HashMap,非线程安全)
核心特性
• 底层:HashMap + 双向链表(在 HashMap 基础上增加链表记录插入顺序/访问顺序)。
• 排序:有序(默认按 插入顺序,可设置为按 访问顺序,访问后元素移至链表尾部)。
• null 支持:同 HashMap(Key 1 个 null,Value 多个 null)。
• 效率:略低于 HashMap(多了链表维护成本),增删查仍接近 O(1)。
• 适用场景:需要保留键值对顺序的场景(如历史记录、有序配置)。
四、避坑点
1. Key 必须重写 hashCode() 和 equals():尤其是自定义对象作为 Key 时,否则会导致 Key 重复、查询不到 Value(HashMap/LinkedHashMap 必做,TreeMap 可因排序省略,但建议统一重写)。
2. 避免多线程操作非线程安全 Map:HashMap/LinkedHashMap/TreeMap 并发修改会抛异常,高并发用 ConcurrentHashMap,低并发可加 synchronized 锁。
3. 注意 null 处理差异:TreeMap/ConcurrentHashMap 的 Key 不能为 null,使用时需提前判断,避免空指针。
4. HashMap 初始容量优化:若已知存储数据量,可提前设置初始容量(如存储 1000 个元素,设为 1000/0.75≈1333),减少扩容次数,提升效率。
五、常用场景总结
• 单线程通用场景:HashMap(首选)。
• 单线程有序场景:LinkedHashMap(插入/访问顺序)
• 数据字典/配置存储:HashMap/LinkedHashMap。
六、代码
1.
package testmap;
import java.util.*;
public class TestMap1 {
public static void main(String[] args) {
Map<Integer,String> works = new HashMap<>();
works.put(100,"姓名");
works.put(103,"姓名");
works.put(102,"姓名");
works.put(102,"姓名");//修改
System.out.println("集合中键对的个数"+ works.size());
System.out.println("根据键获取值"+works.get(102));
System.out.println("判断是否包含某个值"+works.containsKey(108));
System.out.println("判断是否包含某个值"+works.containsValue("杨洁"));
//1.键遍历:获取集合中所有键:keySet()-->Set集合
Set<Integer> keys = works.keySet();
for(Integer key:keys){
System.out.println(key);
//通过键获取值
String value=works.get(key);
System.out.println(key+"对应值为:"+value);
}
System.out.println("------------------------");
//2.值遍历:获取集合中所有值 values()-->Collection
Collection<String> values=works.values();
for(String v:values){
System.out.println(v);
}
//3.键值对遍历:entrySet()----->获取所有键值对--Set
Set<Map.Entry<Integer,String>> kvs=works.entrySet();
//遍历Set集合获取每个键值对
for(Map.Entry<Integer,String> kv:kvs) {
Integer key = kv.getKey();//获取键值对中键
String value = kv.getValue();//获取键值对中值
System.out.println(key + "--" + value);
}
Scanner sc = new Scanner(System.in);
System.out.println("输入一个工号");int num=sc.nextInt();
if(works.containsKey(num)){
System.out.println(num+"----"+works.get(num));
}else{
System.out.println("查无此人......");
}
System.out.println("请输入一个员工姓名");
String name=sc.next();
if(works.containsValue(name)){
Set<Integer> ks=works.keySet();
for(Integer key :ks) {
if (works.get(key).equals(name)) {
System.out.println(key+"---"+name);
}
}
}else{
System.out.println("查无此人");
}
}
}
2.
package testmap;
import java.util.*;
public class TestMap2 {
public static void main(String[] args) {
Map<Integer,BankUser> users=new HashMap<>();
BankUser u1=new BankUser(1,"姓名",280000.0);
users.put(1,u1);
users.put(2,new BankUser(1,"姓名",280000.0));
users.put(3,new BankUser(1,"姓名",280000.0));
Set<Integer> keys= users.keySet();
for(Integer key:keys){
BankUser user=users.get(key);
System.out.println(key+"----"+user);
}
Scanner sc = new Scanner(System.in);
System.out.println("输入一个用户名");
String name=sc.next();
Set<Map.Entry<Integer,BankUser>> kvs=users.entrySet();
int count=0;
for(Map.Entry<Integer,BankUser> kv :kvs){
Integer key=kv.getKey();
BankUser user = kv.getValue();
if(user.getUserName().equals(name)){
count++;
System.out.println(user);
}
}
if(count==0){
System.out.println("查无此人......");
}
System.out.println("--------------------------");
Collection<BankUser> vs= users.values();
for(BankUser user:vs){
if(user.getBalance()>20000){
System.out.println(user);
}
}
}
}
更多推荐



所有评论(0)