A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ymkspxh 初级黑马   /  2019-4-4 09:14  /  749 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

day04--------------------------------------------------------------
        Map集合(映射)
                双列集合        键值对应        键映射值
        HashMap<k, v>
                hashMap的key就是hashSet
                底层1.7数组+链表
                    1.8数组+链表+红黑树
        LinkedHashMap<k, v> extends HashMap
        HashTable(淘汰)
        遍历方式:获得key值->使用key值查找value
                keySet()
        Map集合内部结构
                entry对象 ->  键值对
                        entrySet()
                        getKey()
                        getValue()
        jdk9集合有一种新的初始化方式(了解)
                of方法,一次性给集合添加多种元素
                        List<String> list = List.of("a","aw","h","d","b");
                of方法只适用于List接口、Set接口、Map接口,不适应与它们的实现类
                使用of方法实例化的集合不允许修改(内容和长度)
               
        Debug追踪
       
        HashMap键值冲突(哈希相同)时,如何处理
                不同内容的对象,计算出来的数组索引却一致,这种情况成为哈希冲突
                key不变,value覆盖
               
        HashMap的数据结构
                1.7:数组+单链表
                                (为何是单链表?查看源码,hashmap的数据结构entry是单链表结构,没有pre,只有next)
                                (hashmap可以存储null值和null键)(也是和hashtable的不同之处之一)
                                (如何实现一个数组+链表)
                                        单链表[] 对象名 = new 单链表[];
                                (哈希算法-->目的:使每一个元素能均匀的落在数组上面,减少哈希冲突)
                                (已经出现哈希冲突后,元素怎么挂上链表呢?1.7采用头插法
                                                                                                                 1.8采用尾插法
                                                                                                                        因为在多线程的情况下头插法可能会造成闭环)
                1.8:数组+单链表+红黑树
               
                【hashCode怎么算出来的?】
                        使用的是 哈希冲突算法
                        源码(1.8): 针对key,取到它的hashcode,然后(hashCode >> 16) ^ hashCode  (拿hashCode右移16位取到高16位,再对hashCode本身(也就是低16位)取异或)
                        目的是让每一位都尽可能的参与运算(让01出现的尽量平衡)
                                哈希码是一个int类型的数字:int数据4字节32位
                                hashCode右移16位,分成高16位和低16位,拿低16位对高16位取异或
                                        目的是尽可能的让每一位都参与运算
                                                为什么取异或?
                                                        因为在位操作里 异或 是取出'0'、'1'值尽量平均的操作
                                                为减少hashMap冲突,针对数组长度,必须是一个偶数位(2的n次幂)
                                                        因为偶数位-1才能是一个奇数位,只有奇数位的二进制码的最后一位才是1
                                                        二进制码最后一位必须是1,取异或才有可能是0也可能是1
                                                                (最后一位如果为0,取异或必定为0-->全1为1,其他为0)
                                                        才能让高16位和低16位都参与运算
                        1.7的情况:尽管已经尽可能的优化了哈希冲突算法使其尽量的减少冲突,但由于数组下是链表结构,终究还是会影响效率,所以在1.8之后,数组下的链表到达7个元素后,会转换成"红黑树"结构
                       
                hashMap的扩容机制
                        默认数组装满后需要扩容,new一个新的数组装填
                                原来的算法:key的hash和old数组长度-1进行运算得到位置
                                (hashTable做法)扩容算法:key的hash和new数组长度-1进行同样的运算得到位置
                        但是这种操作不够效率,hashMap源码采用
                                e的hash对oldCap进行&操作,看值的倒数第5位是否等于0,再根据是否等于0,决定是否扩容
                                        使用:老数组长度 & hash 去判断结果倒数第5位是否为0
                                        因为:要判断原来的元素在新数组上是否移动,实际上只需要看 & 后的倒数第5位是否为0,为0不移动直接使用,为1移动
                                                移动的大小刚好是原来的长度 -->  oldCap  
                       
                hashMap的默认域值是12
                        默认装载因子0.75 * (默认初始化大小1<<4=16) = 12
                       
                hashMap的数组默认长度 1 << 4 = 16

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马