一、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);
            }
        }

    }

}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐