== 比较两个对象的内存地址是否相同、Equals默认的情况下比较两个对象的内存地址
优点:不需要考虑hash碰撞的问题 缺点:时间复杂度为O(n)
单向链表 数组初始容量:16 元素头插法 hashmap中key如果没有发生碰撞的问题,get查询时间复杂度是O(1),直接根据下标查询。 如果发生hash碰撞问题(hashcode值相同,内容不同),复杂度为O(n)
无序、散列存放 元素尾插法 遍历的时候从数组0开始遍历每个链表,遍历结果存储顺序不保证一致。 如果需要根据存储顺序保存,可以使用LinkedHashMap底层是基于双向链表存放 LinkedHashMap基于双向链表实现 HashMap基本单向链表实现
有序的HashMap集合 存放顺序 双向链表 效率比HashMap低, 原理:将每个index链表实现关联
LRU(最近少使用)缓存淘汰算法 LFU(最不经常使用算法)缓存淘汰算法 ARC(自适应缓存替换算法)缓存淘汰算法 FIFO(先进先出算法)缓存淘汰算法 MRU(最近最常使用算法)缓存淘汰算法
实现LRU算法 插入顺序:先添加的在前面,后添加的在后面。修改操作不影响顺序 执行get/put操作后,其对应的键值对会移动到链表末尾,所以最末尾的是最近访问的,最开始的是最久没有被访问的,这就是访问顺序。
其中参数accessOrder就是用来指定是否按访问顺序,如果为true,就是访问顺序,false根据新增顺序
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
为什么n-1变成一个奇数? 每次扩容都扩容成2的幂,不是奇数hash碰撞概率较大
1、保证不会发生数组越界 首先我们要知道的是,在HashMap,数组的长度按规定一定是2的幂。因此,数组的长度的二进制形式是:10000…000, 1后面有偶数个0。 那么,length - 1 的二进制形式就是01111.111, 0后面有偶数个1。最高位是0, 和hash值相“与”,结果值一定不会比数组的长度值大,因此也就不会发生数组越界。一个哈希值是8,二进制是1000,一个哈希值是9,二进制是1001。和1111“与”运算后,结果分别是1000和1001,它们被分配在了数组的不同位置,这样,哈希的分布非常均匀。