当前位置: 首页 > article >正文

JavaSE——集合8:Map接口

目录

一、Map接口实现类的特点

二、Map接口常用方法

三、Map三组遍历方式

四、练习题(重要)


一、Map接口实现类的特点

Map 接口实现类的特点,使用实现类HashMap解析:

  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
  2. Map 中的 key 和  value 可以是任何引用类型的数据,会封装到HashMap$Node 对象中
  3. Map 中的 key 不允许重复,原因和HashSet 一样
  4. Map 中的 value 可以重复
  5. Map 的key 可以为 null, value 也可以为null;注意 key 为null,只能有一个,value 为null,可以多个
  6. 常用String类作为Map的 key
  7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
public class Map_ {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("no1", "张三"); // k-v
        map.put("no2", "张无忌"); // k-v
        map.put("no1", "张三丰"); // 当有相同的k , 就等价于替换.
        map.put("no3", "张三丰"); // k-v
        map.put(null, null); // k-v
        map.put(null, "abc"); // 等价替换
        map.put("no4", null); // k-v
        map.put("no5", null); // k-v
        map.put(1, "赵敏"); // k-v
        map.put(new Object(), "金毛狮王"); // k-v

        // 通过get 方法,传入 key ,会返回对应的value
        System.out.println(map.get("no2")); // 张无忌

        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }
        // no2=张无忌
        // null=abc
        // no1=张三丰
        // 1=赵敏
        // java.lang.Object@5594a1b5=金毛狮王
        // no4=null
        // no3=张三丰
        // no5=null
    }
}

8.Map存放数据的key-value示意图,一堆k-v是放在一个HashMap$Node中的,又因为Node实现了Entry接口,也可以说一对k-v就是一个Entry。

原理详解:很重要!!!

掌握了这里,在遍历map集合时,才能知道,使用不同的遍历方式得到的返回值类型。

1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null);
2. k-v 为了方便遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry,而一个Entry  对象就有k,v EntrySet<Entry<K,V>>  即: transient Set<Map.Entry<K,V>> entrySet;
3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node
   这是因为Node实现了Map.Entry接口,即:static class Node<K,V> implements Map.Entry<K,V>;
   当有一个类实现了一个接口,该类的对象实例就可以赋给接口,这里就体现了多态;
   所以,Node<K,V> 就可以赋值给Map.Entry<K,V>;
4. 当把 HashMap$Node 对象 "存放"到 entrySet 后,就方便遍历了;
   因为 Map.Entry 提供了重要方法:K getKey(); V getValue();
   注意:这里不是真正的存放到entrySet中!!! 是多态!!!

public class MapSource_ {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("no1", "张三"); // k-v
        map.put("no2", "张无忌"); // k-v
        map.put(new Car(), new Person()); // k-v

        // Set的类型是EntrySet,EntrySet集合中存放的是多个Entry对象,而每个Entry对象里面都有K,V
        Set set = map.entrySet();
        System.out.println(set.getClass());// HashMap$EntrySet

        for (Object obj : set) {
            // System.out.println(obj.getClass()); // HashMap$Node
            // 为了从 HashMap$Node 取出k-v
            // 1. 先做一个向下转型
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "-" + entry.getValue() );
        }
        // no2-张无忌
        // no1-张三
        // com.testdemo.map_.Car@3b6eb2ec-com.testdemo.map_.Person@73f792cf


        // Set和Collection只是一个引用
        // set1的实际运行类型是KeySet,是Set的一个子类
        Set set1 = map.keySet();
        System.out.println(set1.getClass());
        // class java.util.HashMap$KeySet

        // values的实际运行类型是Values,是Collection的一个子类
        Collection values = map.values();
        System.out.println(values.getClass());
        // class java.util.HashMap$Values
    }
}

class Car {}

class Person{}

二、Map接口常用方法

  1. put:添加
  2. remove:根据键删除映射关系
  3. get:根据键获取值
  4. size:获取元素个数
  5. isEmpty:判断个数是否为0
  6. clear:清楚
  7. containsKey:查找键是否存在 
public class MapMethod {
    public static void main(String[] args) {
        Map map = new HashMap();

//         put:添加
        // key相同,value不同
        map.put("梁山伯", new Book("", 100)); // OK
        map.put("梁山伯", "祝英台"); // 替换
        // key不同,value相同
        map.put("林黛玉", "贾宝玉"); // OK
        map.put("薛宝钗", "贾宝玉");// OK
        // value为null
        map.put("张三", null); // OK
        // key为null
        map.put(null, "李四"); // OK
        map.put("jack", "rose");// OK

        System.out.println("map=" + map);
        // map={null=李四, 张三=null, 薛宝钗=贾宝玉, 梁山伯=祝英台, 林黛玉=贾宝玉, jack=rose}


//        remove:根据键删除映射关系
        map.remove(null);
        System.out.println("map=" + map);
        // map={张三=null, 薛宝钗=贾宝玉, 梁山伯=祝英台, 林黛玉=贾宝玉, jack=rose}


//        get:根据键获取值
        Object val = map.get("jack");
        System.out.println("val=" + val);
        // val=rose


//        size:获取元素个数
        System.out.println("k-v=" + map.size());
        // k-v=5


//        isEmpty:判断个数是否为0
        System.out.println(map.isEmpty()); // false


//        clear:清除k-v
        // map.clear();
        // System.out.println("map=" + map); // map={}

//        containsKey:查找键是否存在
        System.out.println("结果=" + map.containsKey("林黛玉"));
        // 结果=true
    }
}

class Book {
    private String name;
    private int num;

    public Book(String name, int num) {
        this.name = name;
        this.num = num;
    }
}

三、Map三组遍历方式

        Map集合的三组遍历方式分为:遍历所有key;遍历所有value;通过entrySet获取k-v

  1. keySet:获取所有的键
  2. entrySet:获取所有关系k-v
  3. values:获取所有的值 

        注意:一定要了解Map接口实现类的特点以后再来遍历,知道每次遍历出来时什么数据类型,才知道如何向下转型,在什么时候进行向下转型,而不是机械地记忆这些遍历方式。

public class MapFor {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("梁山伯", "祝英台");
        map.put("林黛玉", "贾宝玉");
        map.put("薛宝钗", "贾宝玉");
        map.put("张三", null);
        map.put(null, "李四");
        map.put("jack", "rose");

        // 第一组: 先取出 所有的Key , 再通过Key 取出对应的Value
        Set keyset = map.keySet();
        // (1) 增强for
        System.out.println("-----第一种方式-------");
        for (Object key : keyset) {
            System.out.println(key + "-" + map.get(key));
        }
        // null-李四
        // 张三-null
        // 薛宝钗-贾宝玉
        // 梁山伯-祝英台
        // 林黛玉-贾宝玉
        // jack-rose

        // (2) 迭代器
        System.out.println("----第二种方式--------");
        Iterator iterator = keyset.iterator();
        while (iterator.hasNext()) {
            Object key = iterator.next();
            System.out.println(key + "-" + map.get(key));
        }
        // null-李四
        // 张三-null
        // 薛宝钗-贾宝玉
        // 梁山伯-祝英台
        // 林黛玉-贾宝玉
        // jack-rose


        // 第二组: 把所有的values取出
        Collection values = map.values();
        // 这里可以使用所有的Collections使用的遍历方法
        // (1) 增强for
        System.out.println("---取出所有的value 增强for----");
        for (Object value : values) {
            System.out.println(value);
        }
        // 李四
        // null
        // 贾宝玉
        // 祝英台
        // 贾宝玉
        // rose

        // (2) 迭代器
        System.out.println("---取出所有的value 迭代器----");
        Iterator iterator2 = values.iterator();
        while (iterator2.hasNext()) {
            Object value = iterator2.next();
            System.out.println(value);
        }
        // 李四
        // null
        // 贾宝玉
        // 祝英台
        // 贾宝玉
        // rose


        // 第三组: 通过EntrySet 来获取 k-v
        Set entrySet = map.entrySet(); // Set<Map.Entry<K, V>> entrySet();
        System.out.println("---------第三种方式--------");
        // (1) 增强for
        System.out.println("----使用EntrySet 的 for增强(第3种)----");
        for (Object entry : entrySet) {
            // 将entry 向下转型 转成 Map.Entry
            Map.Entry m = (Map.Entry) entry;
            System.out.println(m.getKey() + "-" + m.getValue());
        }
        // null-李四
        // 张三-null
        // 薛宝钗-贾宝玉
        // 梁山伯-祝英台
        // 林黛玉-贾宝玉
        // jack-rose


        System.out.println("---------第四种方式--------");
        // (2) 迭代器
        System.out.println("----使用EntrySet 的 迭代器----");
        Iterator iterator3 = entrySet.iterator();
        while (iterator3.hasNext()) {
            Object entry = iterator3.next();
            // System.out.println(next.getClass());// HashMap$Node -实现-> Map.Entry (getKey,getValue)
            // 向下转型 Map.Entry
            Map.Entry m = (Map.Entry) entry;
            System.out.println(m.getKey() + "-" + m.getValue());
        }
        // null-李四
        // 张三-null
        // 薛宝钗-贾宝玉
        // 梁山伯-祝英台
        // 林黛玉-贾宝玉
        // jack-rose
    }
}

四、练习题(重要)

该练习题能够充分检验Map遍历原理是否真正掌握:

        使用HashMap添加3个员工对象,员工类:姓名、工资、员工id。

        要求:键:员工id        值:员工对象        并遍历显示工资>18000的员工

public class MapExercise {
    public static void main(String[] args) {
        Map map = new HashMap();
        Employee employee1 = new Employee("张三", 24000, 1);
        Employee employee2 = new Employee("李四", 15000, 2);
        Employee employee3 = new Employee("王五", 20000, 3);
        map.put(employee1.getId(), employee1);
        map.put(employee2.getId(), employee2);
        map.put(employee3.getId(), employee3);

        // 显示工资>18000的员工
        System.out.println("--------第一组:先取出所有的key---------");
        Set keySet = map.keySet();
        System.out.println("-------方式一:-------");
        // 增强for
        for (Object key : keySet) {
            Employee employee = (Employee) map.get(key);
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
        System.out.println("-------方式二:-------");
        // 迭代器
        Iterator iterator = keySet.iterator();
        while (iterator.hasNext()) {
            Object key = iterator.next();
            Employee employee = (Employee) map.get(key);
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
        System.out.println("--------第二组:先取出所有的value---------");
        System.out.println("-------方式一:-------");
        Collection collection = map.values();
        for (Object obj : collection) {
            Employee employee = (Employee) obj;
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
        System.out.println("-------方式二:-------");
        // 迭代器
        Iterator iterator1 = collection.iterator();
        while (iterator1.hasNext()) {
            Employee employee = (Employee) iterator1.next();
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
        System.out.println("--------第三组:使用entrySet---------");
        Set entrySet = map.entrySet();

        System.out.println("-------方式一:-------");
        // 增强for
        for (Object entry : entrySet) {
            Map.Entry entry1 = (Map.Entry) entry;
            Employee employee = (Employee) entry1.getValue();
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
        System.out.println("-------方式二:-------");
        // 迭代器
        Iterator iterator2 = entrySet.iterator();
        while (iterator2.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator2.next();
            Employee employee = (Employee) entry.getValue();
            if (employee.getSalary() > 18000) {
                System.out.println(employee);
            }
        }
    }
}

class Employee {
    private String name;
    private double salary;
    private int id;

    public Employee(String name, double salary, int id) {
        this.name = name;
        this.salary = salary;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                ", id=" + id +
                '}';
    }
}

http://www.kler.cn/a/349570.html

相关文章:

  • LabVIEW温度修正部件测试系统
  • AI编程:如何编写提示词
  • 项目集成GateWay
  • zabbix7 配置字体 解决中文乱码问题(随手记)
  • RK3568 opencv播放视频
  • C++ 堆栈分配的区别
  • 数组合并与排序练习题
  • 管理者如何开展和布置工作?
  • 【Java 并发编程】单例模式
  • 牛的旅行——Floyd
  • 【K8S系列】Kubernetes 集群中的网络常见面试题
  • 【代码随想录Day43】动态规划Part11
  • Scala入门基础(10)高级函数
  • Windows 11 开发详解:工具与高级用法
  • FLINK SQL UDF
  • Crawl4AI:用几行代码打造强大的网页爬虫
  • 猎板PCB:军工武器系统中的PCB线路板技术要求
  • 【30天玩转python】最后复习与总结
  • C++ 的特性可以不用在主函数中调用
  • 如何恢复MaxKB系统管理员账号密码
  • linux Load Average 计算
  • 元数据 - iXML
  • ubuntu24开启启动脚本
  • 全面掌握 Linux 服务管理:从入门到精通
  • Json-Rpc框架(项目设计 —— 服务端客户端 模块功能划分简介)
  • 不启动容器直接进入Docker镜像里执行命令