arrayMap
主要数据结构:hash数组和数据数组
描述:有2个数组,一个存放key.hashcode(),另一个实际存放数据的数组 存放key和value(偶下表放key,+1下标放value,所以该数组大小至少为hash数组的2倍),hash数组存放hash值为有序存放,查找的时候根据key的 hash用二分法查找,找到的下标作为返回值,该下标*2 = 实际存放数据下标的key 的下标, +1为value下标
hash碰撞:keyhash一样就认为是同一个对象,直接替换value
enumMap
主要数据结构:数组
描述:本质就是一个数据,key为 Enum类型,获取 int order() 为下标,数组内容存放value
hash碰撞:不用key的hash做索引,所以只要order一样,则认为key是一样的
hashMap
主要数据结构:数组+下标哈希
描述:有 Node<K,V> table[] 数组, 下标作为hash表 keyHash & (table.length - 1) ,按位与做了hash散列的映射,获得的掩码值作为下标, 当table 的数据类型是 TreeNode 时,一般用在LinkdHashMap 中。
hash碰撞:
1.拉链法(链表)
hash一样时,还要判断 value , == 和 equals() 都成立则认为是同一个对象,否则认为是hash碰撞,在同一个hash桶内,用单向链表链接相同hash的元素,并从第一个元素开始遍历链表,依次用 == equals() 判断是否是同一个value对象,若是则替换value,否则直到链表尾都不存在匹配上的对象,则通过可 覆写 函数newNode()新建一个node,接入链表尾部。
2.红黑树
identityHashMap
主要数据结构:数组+下标哈希
描述:用Object[] table; 做存储,下标为hash表(和hashmap类似),不同是key的hashcode为 h=System.identityHashCode() 获得,并且hash运算为 ((h << 1) - (h << 8)) & (length - 1) ,只有与table的length-1 做位与相同 (Multiply by -127, and left-shift to use least bit as part of hash 没理解,)根据key和len算出的下标,存放key对象, 该下标+1 处,存放value对象。
hash碰撞:再次散列:依序往后顺延一个存储位(基于上次index的值+2),如果key对象是同一个 (==),则认为是同一个元素,否则认为只是不同key对象,产生的hash碰撞。
LinkedHashMap
主要数据结构:用双向链表存储
描述:通过 覆写 父类获取Node 的函数 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) ,来返回 LinkedHashMapEntry 类型的Node ,该Node 多了 前,后,节点的指针,作为双向链表节点使用。LinkedHashMap还多了 head,tail 双向链表的节点。
在删除时,覆写 afterNodeRemove(Node<K,V> e) 方法,将删除的节点 从双向链表中剔除(根据before和after),最后刷新head 和 tail
linkedhashmap是有序的,在使用迭代器的时候可以看到遍历顺序和插入顺序相同,这是和hashmap是无序的(迭代顺序依照keyhash的数值大小),linkedhashmap保持有序的原因是,插入数据时,利用LinkedHashMapEntry的 before 引用到tail,所以遍历时,根据从head 节点的 after 一直到 tail 节点,便可以还原出和插入顺序一致的遍历顺序。?
LinkedHashMap有序,可分为插入顺序和访问顺序两种。如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)
hash碰撞:因继承hashMap,所以和hashMap一致。(拉链法)
TreeMap
主要数据结构:红黑树
描述:用 TreeMapEntry<K,V> root; 存储树的根节点,节点主要记录,左右父节点,颜色,key,value。插入时根据比较器(传入key的值)返回的相对大小,从树根向下查找相同节点,只要比较器认为key相同则TreeMap认为元素相同,如果没有找到相同元素,则在最后遍历到位置的树的末尾插入新节点,然后根据2-3树的性质上浮超过-3元素(一个节点中有超过2个子节点的情况)的节点的中间子节点,并通过左右旋转(AVL树相关算法)修复树最大最小树深度不超过1的特性。
hash碰撞:比较器认为key相同则元素相同,直接替换。不存在hash的问题。