From a6b89d1e5b4ab83ac28365c790be5e390aff5c41 Mon Sep 17 00:00:00 2001 From: chenjing Date: Mon, 9 Mar 2020 23:48:54 +0800 Subject: [PATCH] 83 --- second/week_01/83/week1.md | 84 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/second/week_01/83/week1.md b/second/week_01/83/week1.md index dd10eef..6b75714 100644 --- a/second/week_01/83/week1.md +++ b/second/week_01/83/week1.md @@ -19,8 +19,8 @@ add(int index,E elemement):添加到指定位置,平局时间复杂度为O(n) 5. 大小增1 E get(int index) 时间复杂度为O(1) - 1.检查是否越界 - 2.返回索引位置处的元素 + 1. 检查是否越界 + 2. 返回索引位置处的元素 E remove(int index)时间复杂度为O(n) 1. 检查是否越界 @@ -50,6 +50,7 @@ key/value 结构存储,查询和修改的速度都很快,O(1)的平均时间 数组查询效率为O(1),链表查询效率O(k),红黑树查询效率O(log k) 主要属性 +```java /** * 默认的初始容量为16 */ @@ -99,6 +100,7 @@ int threshold; * 装载因子 */ final float loadFactor; //默认为0.75 +``` Node是一个单链表节点,TreeNode是双向链表继承自LinkedHashMap有parent,left,right,prev,red(boolean) @@ -114,3 +116,81 @@ put(K key, V value) 10.如果插入了元素,则数量加1并判断是否需要扩容; resize()扩容 +TreeNode.putTreeVal(..)插入元素到红黑树中的方法 +get(Object key) +1. 计算key的hash值; +2. 找到key所在的桶及其第一个元素; +3. 如果第一个元素的key等于待查找的key,直接返回; +4. 如果第一个元素是树节点就按树的方式来查找,否则按链表方式查找; + +# LinkedHashMap +LinkedHashMap = LinkedList + HashMap +内部维护了一个双向链表,能保证元素按插入顺序访问,也能以访问顺序访问(这个是什么鬼??!),可以用来实现LRU缓存策略。 + +LinkedHashMap继承了HashMap,拥有hashmap所有的特性,因加了LinkedList则额外增加了按一定顺序访问的特性。增加或删除元素的时候需要维护在hashmap中的存储,也要维护linkedList中的存储,所以性能上来说会比HashMap稍慢 + +主要属性 +```java +/** +* 双向链表头节点 +*/ +transient LinkedHashMap.Entry head; + +/** +* 双向链表尾节点 +*/ +transient LinkedHashMap.Entry tail; + +/** +* 是否按访问顺序排序,如果为false则按插入顺序存储元素, +* 如果是true则按访问顺序存储元素 +*/ +final boolean accessOrder; +``` +构造 +```java +public LinkedHashMap(int initialCapacity, +float loadFactor, +boolean accessOrder){ +super(initialCapacity, loadFactor); +this.accessOrder = accessOrder; +} +``` +没有赋值的accessOrder都默认为false,说明双向链表是按插入顺序存储元素。 +如果为true,就实现了按访问顺序存储元素,是LRU缓存策略关键。(LRU究竟是个什么鬼??!!待查) + +```java +void afterNodeInsertion(boolean evict) { + if(evict && (fist = head) != null && removeEldestEntry(first)){ + } +} + +``` +如果evict为true,且头节点不为空,且确定移除最老元素,就调用HashMap.removeNode()把头节点移除(这里的头节点是双向链表的头节点,而不是某个桶中的第一个元素) + +```java +public V get(Object key) +``` +如果查找到了元素,且accessOrder为true,则调用afterNodeAccess()方法把访问的节点移到双向链表的末尾。 + +# 终于看到了彩蛋 +LRU 缓存淘汰策略 Least Recently Used +```java +class LRU extends LinkedHashMap{ +// 保存缓存的容量 +private int capacity; +public LRU(int capacity,float loadFactor){ + super(capacity,loadFactor,true); + this.capacity = capacity; +} + +@Override +protected boolean removeEldestEntry(Map.Entry eldest){ + // 当元素个数大于了缓存的容量, 就移除元素 + return size() > this.capacity; +} + + +} + +``` -- Gitee