JavaSE学习笔记:集合框架之Map


一、接口Map

在这里插入图片描述

1.1 Map集合特点

	1.Map集合和Collection没有任何关系
	2.Map集合以key和value的这种键值对的方式存储数据
	3.key和value都是存储Java对象的内存地址
	4.所有Map集合的一大特点就是:无需不可重复
	5.Map集合的key和set集合存储元素特点相同

1.2 Map集合中的常用方法

	void clear() 
	从该地图中删除所有的映射(可选操作)。  

	boolean containsKey(Object key) 
	如果此映射包含指定键的映射,则返回 true 。  
	boolean containsValue(Object value) 
	如果此Map将一个或多个键映射到指定的值,则返回 true 。  

	V get(Object key) 
	返回到指定键所映射的值,或 null如果此映射包含该键的映射。  

	boolean isEmpty() 
	如果此Map不包含键值映射,则返回 true 。 

	Set<K> keySet() 
	返回此Map中包含的键的Set视图。  

	V put(K key, V value) 
	将指定的值与该映射中的指定键相关联(可选操作)。  

	V remove(Object key) 
	如果存在(从可选的操作),从该地图中删除一个键的映射。  

	Collection<V> values() 
	返回此地图中包含的值的Collection视图。  

	Set<Map.Entry<K,V>> entrySet()
	返回此地图中包含的映射的Set视图。 
        //创建Map集合
        Map<Integer,String> map = new HashMap();
        //向Map集合中添加键值对
        map.put(1, "老王");
        map.put(2, "老王");
        map.put(3, "老张");
        map.put(4, "李四");
        //通过key获取value
        System.out.println(map.get(1));

        //获取键值对的数量
        System.out.println(map.size());

        //通过key删除value
        map.remove(2);
        for (Integer key : map.keySet()) {
            System.out.println(key);
        }

        //判断是否包含某个key和value
        //contains方法底层调用的都是equals方法进行比对,所以自定义的类型需要重写equals方法
        System.out.println(map.containsKey(4));                               //true
        System.out.println(map.containsKey(new Integer(4)));            //true
        System.out.println(map.containsValue("老王"));                        //true
        System.out.println(map.containsValue(new String("老王")));    //true

        //获取所有的value值
        Collection<String> values = map.values();
        System.out.println(values);
        //Set<Map.Entry<K,V>> entrySet()
        //返回此地图中包含的映射的Set视图。
        Set set = map.keySet();
        for (Object o : set) {
            System.out.println(o);
        }

1.3 遍历Map集合的几种方式

1.3.1 通过迭代器遍历

        //通过迭代器的方式遍历Map
        Set<Integer> keys = map.keySet();
        Iterator<Integer> iterator = keys.iterator();
        while (iterator.hasNext()){
            Integer key = iterator.next();
            String value = map.get(key);
            System.out.println("key = " + key + "," + "value = " + value);
        }

1.3.2 通过 entrySet()方法遍历

//        Set<Map.Entry<K,V>> entrySet()
//        返回此地图中包含的映射的Set视图。
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()){
            Map.Entry<Integer, String> next = iterator.next();
            System.out.println(next);
        }

1.3.3 通过增强for循环遍历

        //通过增强for循环遍历一
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        for (Map.Entry<Integer, String> node : entrySet) {
            Integer key = node.getKey();
            String value = node.getValue();
            System.out.println(key + "=" + value);
        }

		//通过增强for循环遍历二
        Set<Integer> keys = map.keySet();
        for (Integer key : keys) {
            String value = map.get(key);
            System.out.println(key + "=" + value);
        }

二、HashMap

2.1 HashMap概述

  • HashMap底层是哈希表/散列表数据结构
  • 有关哈希表的数据结构:
    • 哈希表是一个数组和单向链表的结合体
    • 哈希表将两种数据结构融合在一起,充分发挥各自的优点
  • 有关HashMap底层源码:
    • HashMap底层实际上就是数组transient Node<K,V>[] table;
    • 静态内部类HashMap.Node:static class Node<K,V> implements Map.Entry<K,V>
      • final int hash;哈希值哈希值是key的hashCode()方法的执行结果,hash值通过hash算法获得,可以转化为数组下标
      • final K key;存储到Map集合中的key
      • V value;存储到Map集合中的value
      • Node<K,V> next;下一个内存节点的地址

2.2 哈希表的数据结构

2.2.1 Map方法:put(K key, V value) 实现原理

  • 将key与value封装到Node对象中区,底层调用key的hashCode()方法得出hash值,通过哈希算法将hash值转化为数组的下标,如果下标没有任何元素,那么就把Node添加到这个位置上,如果下标对应的位置上有链表,此时会把key值与链表上的每一个节点中的key值进行equals()比较,如果返回false,这个新节点就被添加到链表末尾,如果返回的是true,这个节点的value将会被覆盖

2.2.2 Map方法:get(Object key) 实现原理

  • 首先调用key的hashCode()方法得出哈希值,通过哈希算法转化为数组下标,通过数组下标快速定位到某个位置,如果这个位置没有元素则返回null,如果这个位置上有单向链表,那么会用key和单向链表中的key进行equals()比较,如果equals返回false,那么get方法返回null,如果equals()返回true,那么这个节点的value就是我们要寻找的value,get()方法会最终返回到这个value值

2.2.3 哈希碰撞

  • 如果o1与o2的hash值相同,一定是放到同一链表上
  • 如果o1与o2的hash值不同,但由于哈希算法执行结束后转换的数组下标可能相同,此时会发生“哈希碰撞”

2.2.4 总结

  • HashMap集合的key无序,不可重复,equals()方法保证了HashMap集合中的key不可重复,如果key重复了,value值会被覆盖掉
  • HashMap集合key部分的元素其实就是放到HashSet集合中,所以HashSet集合中的元素与HashMap集合中key部分的元素需要重写hashCode()与equals()方法
  • 哈希表HashMap使用不当无法发挥其性能,如果将所有的hashCode()方法返回固定值,那么会导致底层哈希表编程纯单向链表,这种情况我们便称为:散列不均匀如果hashCode()返回值都设定为不一样的值,那么哈希表就成了一维数组,也是一种散列不均匀
  • HashMap集合的默认初始化容量是16,且初始化容量必须是2的倍数默认的加载因子是0.75 ,底层数组的容量达到75%的时候开始扩容,每次扩容为原容量的二倍,注意:【HashMap集合初始化容量必须是2的倍数】
  • HashMap集合中的key与value允许null

2.3 JDK8后的版本对HashMap的优化

  • 在JDK8以后版本中,如果哈希表单向链表中的元素 超过8个 ,单向链表这种数据结构会变成 红黑树数据结构 ,当 红黑树上的节点小于6个 的时候,会 重新把红黑树变成单向链表数据结构,这种方式提高了检索效率

三 、关于HashCode()与equals()方法

        Student s1 = new Student("张三");
        Student s2 = new Student("张三");
        //调用equals()方法
        System.out.println(s1.equals(s2));  //重写前返回的是false,重写后返回true

//        System.out.println("s1的hashCode:" + s1.hashCode());     //重写前:s1的hashCode:1915910607
//        System.out.println("s2的hashCode:" + s2.hashCode());     //重写前:s2的hashCode:284720968

        System.out.println("s1的hashCode:" + s1.hashCode());     //重写后:s1的hashCode:774920
        System.out.println("s2的hashCode:" + s2.hashCode());     //重写后:s2的hashCode:774920
  • 在Map集合中的存取过程,都是先调用hashCode()方法,然后再调用equals()方法
  • put(K key, V value) 方法中,K.hashCode()方法返回哈希值,哈希值经过哈希算法转换为数组下标,如果数组下标位置上是null,equals()方法就不需要执行
  • 在==get(Object key)==方法中,K.hashCode()方法返回哈希值,哈希值经过哈希算法转换为数组下标,如果 数组下标位置上是null,equals()方法就不需要执行

四、HashTable集合

  • HashTable的key与value值都不能为null ,而HashMap的key与value可以为null
  • HashTable方法都带有synchronized,所以都是 线程安全
  • HashTable与HashMap地城都是哈希表数据结构,HashTable初始容量为11,扩容因子是0.75,每次扩容为【原容量 * 2 + 1】

五、TreeMap集合

  • TreeMap集合底层是二叉树
  • TreeSet集合放入的数据其实放入了一个TreeMap集合中
  • TreeMap与TreeSet集合是可排序集合,集合中的元素是自动按照大小顺序排序的,不可排序自定义类型
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值