Bläddra i källkod

增加了云平台安装文档,
增加了hashmap课程的文档

seamew 3 år sedan
förälder
incheckning
2cc7c0232e

+ 74 - 0
后端/JAVA高阶/HashMap/第一节课数组加链表&时间复杂度的对比.md

@@ -0,0 +1,74 @@
+## 为什么重写equals方法还要重写hashcode方法
+
+1. Object 的 hashcode 方法是本地方法,也就是用 c 或 c++ 实现的,该方法直接返回对象的内存地址,让后再转换整数。
+2.	Equals方法
+	1.	两个对象的Hashcode值相等,但是两个对象的内容值不一定相等;---Hash冲突的问题
+	2.	两个对象的值Equals比较相等的情况下,则两个对象的Hashcode值一定相等;
+
+ == 比较两个对象的内存地址是否相同、Equals默认的情况下比较两个对象的内存地址
+1. 【强制】关于 hashCode 和 equals 的处理,遵循如下规则:
+1) 只要覆写 equals,就必须覆写 hashCode。
+2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须覆写这两个方法。
+3) 如果自定义对象作为 Map 的键,那么必须覆写 hashCode 和 equals。
+4)为了避免内存泄漏----强引用
+说明:String 已覆写 hashCode 和 equals 方法,所以我们可以愉快地使用 String 对象作为 key 来使用。
+
+## HashMap底层实现原理
+
+### 1. 基于Arraylist集合方式实现
+
+优点:不需要考虑hash碰撞的问题 缺点:时间复杂度为O(n)
+
+### 2. 基于数组+链表方式实现(Jdk1.7)
+
+单向链表
+数组初始容量:16
+元素头插法
+hashmap中key如果没有发生碰撞的问题,get查询时间复杂度是O(1),直接根据下标查询。
+如果发生hash碰撞问题(hashcode值相同,内容不同),复杂度为O(n)
+
+### 3. 基于数组+链表方式+红黑树(Jdk1.8)
+
+## HashMap底层是有序存放的吗?
+
+无序、散列存放
+元素尾插法
+遍历的时候从数组0开始遍历每个链表,遍历结果存储顺序不保证一致。
+如果需要根据存储顺序保存,可以使用LinkedHashMap底层是基于双向链表存放
+LinkedHashMap基于双向链表实现
+HashMap基本单向链表实现
+
+## LinkedHashMap实现缓存淘汰框架
+
+有序的HashMap集合 存放顺序 双向链表
+效率比HashMap低,
+原理:将每个index链表实现关联
+
+LRU(最近少使用)缓存淘汰算法
+LFU(最不经常使用算法)缓存淘汰算法
+ARC(自适应缓存替换算法)缓存淘汰算法
+FIFO(先进先出算法)缓存淘汰算法
+MRU(最近最常使用算法)缓存淘汰算法
+
+实现LRU算法
+插入顺序:先添加的在前面,后添加的在后面。修改操作不影响顺序
+执行get/put操作后,其对应的键值对会移动到链表末尾,所以最末尾的是最近访问的,最开始的是最久没有被访问的,这就是访问顺序。
+
+其中参数accessOrder就是用来指定是否按访问顺序,如果为true,就是访问顺序,false根据新增顺序
+
+## HashMap如何降低Hash冲突概率
+
+```
+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,它们被分配在了数组的不同位置,这样,哈希的分布非常均匀。
+
+
+

+ 124 - 0
后端/JAVA高阶/HashMap/第二节课HashMap源码分析.md

@@ -0,0 +1,124 @@
+## 分析1.8
+
+核心参数:
+
+1. HashMap初始容量
+static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
+2. HashMap的最大容量
+static final int MAXIMUM_CAPACITY = 1 << 30;
+3. 加载因子    16×0.75=12 一旦size大于12提前扩容
+static final float DEFAULT_LOAD_FACTOR = 0.75f;
+4. 链表长度大于8,将链表转换成红黑树
+static final int TREEIFY_THRESHOLD = 8;
+5. 红黑树的节点个数小于6就将红黑树转换为链表
+static final int UNTREEIFY_THRESHOLD = 6;
+6. 数组容量大于64的情况下,将链表转换成红黑树
+static final int MIN_TREEIFY_CAPACITY = 64;
+
+底层采用单向链表
+```
+final int hash;
+final K key;
+V value;
+Node<K,V> next;
+```
+为什么要将key的hash值保存起来?
+下次扩容的时候,能够计算该key在新的table中index值
+```
+// transient不能被序列化
+transient Node<K,V>[] table;
+transient int size;
+// 遍历hashmap集合的时候,防止多线程篡改我们的数据
+transient int modCount;
+// 加载因子
+final float loadFactor;
+```
+
+## 分析hashmap的put方法底层实现原理
+
+```
+final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
+                   boolean evict) {
+        // n是当前table数组的长度,i就是index下标位。table和p临时table大小接受
+        Node<K,V>[] tab; Node<K,V> p; int n, i;
+        // 将全局table=tab判断是否为空,如果为空的情况下,且长度=0开始对table实现扩容,实现懒加载
+        if ((tab = table) == null || (n = tab.length) == 0)
+        	// 默认的大小为16
+            n = (tab = resize()).length;
+        if ((p = tab[i = (n - 1) & hash]) == null)
+            tab[i] = newNode(hash, key, value, null);
+        else {
+            Node<K,V> e; K k;
+            if (p.hash == hash &&
+                ((k = p.key) == key || (key != null && key.equals(k))))
+                e = p;
+            else if (p instanceof TreeNode)
+                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
+            else {
+                for (int binCount = 0; ; ++binCount) {
+                    if ((e = p.next) == null) {
+                        p.next = newNode(hash, key, value, null);
+                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
+                            treeifyBin(tab, hash);
+                        break;
+                    }
+                    if (e.hash == hash &&
+                        ((k = e.key) == key || (key != null && key.equals(k))))
+                        break;
+                    p = e;
+                }
+            }
+            if (e != null) { // existing mapping for key
+                V oldValue = e.value;
+                if (!onlyIfAbsent || oldValue == null)
+                    e.value = value;
+                afterNodeAccess(e);
+                return oldValue;
+            }
+        }
+        ++modCount;
+        if (++size > threshold)
+            resize();
+        afterNodeInsertion(evict);
+        return null;
+    }
+```
+1. n是当前table数组的长度,i就是index下标位。table和p临时table大小接受
+Node<K,V>[] tab; Node<K,V> p; int n, i;
+2. 将全局table=tab判断是否为空,如果为空的情况下,且长度=0开始对table实现扩容,实现懒加载
+if ((tab = table) == null || (n = tab.length) == 0)
+默认的大小为16
+n = (tab = resize()).length;
+获取原来的table容量
+int oldCap = (oldTab == null) ? 0 : oldTab.length;
+下一次扩容的大小
+int oldThr = threshold;
+这一次扩容的大小,下一次扩容的阈值
+int newCap, newThr = 0;
+3. p就是链表
+p = tab[i = (n - 1) & hash]) == null
+4. 如果hash值相等并且equals也相等,直接覆盖
+if (p.hash == hash &&
+((k = p.key) == key || (key != null && key.equals(k))))
+e = p;
+5. 将新的值覆盖
+if (e != null) { // existing mapping for key
+V oldValue = e.value;
+if (!onlyIfAbsent || oldValue == null)
+e.value = value;
+afterNodeAccess(e);
+return oldValue;
+}
+6. 找到该结点
+if (e.hash == hash &&
+((k = e.key) == key || (key != null && key.equals(k))))
+break;
+7. hashmap线程不安全
+防止hashmap线程冲突
+添加新元素
+++modCount;-----fastclass机制
+8. 如果size大于12,提前扩容
+if (++size > threshold)
+if (++size > threshold)
+resize();
+

+ 5 - 5
大数据/K8S/3.使用kubeadm快速部署一个K8s集群.md

@@ -116,11 +116,11 @@ $ systemctl enable kubelet
 
 ```
 $ kubeadm init \
-  --apiserver-advertise-address=192.168.44.146 \
+  --apiserver-advertise-address=192.168.245.22 \
   --image-repository registry.aliyuncs.com/google_containers \
   --kubernetes-version v1.18.0 \
-  --service-cidr=10.96.0.0/12 \
-  --pod-network-cidr=10.244.0.0/16
+  --service-cidr=10.96.0.0/16 \
+  --pod-network-cidr=192.168.0.0/16
 ```
 
 由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址。
@@ -141,8 +141,8 @@ $ kubectl get nodes
 向集群添加新节点,执行在kubeadm init输出的kubeadm join命令:
 
 ```
-$ kubeadm join 192.168.1.11:6443 --token esce21.q6hetwm8si29qxwn \
-    --discovery-token-ca-cert-hash sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
+$ kubeadm join 192.168.245.22:6443 --token esce21.q6hetwm8si29qxwn \
+    --discovery-token-ca-cert-hash sha256:27cfb6d3e84de839eab0824c6bf9373c8be8a2e4549bcb858bd408d917835e66 
 ```
 
 默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,操作如下:

+ 34 - 0
大数据/云平台安装文档/安装云平台环境.md

@@ -0,0 +1,34 @@
+> [TOC]
+
+# 1.离线安装Docker及其相应组件(三台虚拟机都需要安装)
+
+## 1.1离线安装Docker
+
+首先创建```/opt/package```目录存放相应的安装包
+```mkdir /opt/package/```
+
+其次,将安装包目录下的docker19-rpm.zip压缩包放到虚拟机的```/opt/package```目录下,进行解压缩操作,进入目录,使用命令
+```
+unzip docker19-rpm.zip
+rpm -ivh *.rpm  --force --nodeps
+systemctl enable docker && systemctl start docker
+docker --version
+```
+输出docker版本号表示安装成功
+![image-20211108145729544](../../照片/image-20211108145729544.png)
+
+## 1.2离线安装Docker-compose
+
+将安装包目录下的docker-compose-linux-x86_64文件上传到虚拟机的```/opt/package```目录下使用命令
+```
+// 将下载好的文件传入linux系统中,并重命名未docker-compose
+mv docker-compose-linux-x86_64 docker-compose
+// 给予docker-compose文件可执行权限
+chmod u+x docker-compose
+// 将docker-compose文件移至/usr/local/bin
+mv docker-compose /usr/local/bin
+// 查看版本
+docker-compose --version
+```
+输出docker-compose版本号表示安装成功
+![image-20211108154405864](../../照片/image-20211108154405864.png)

BIN
照片/image-20211108145729544.png


BIN
照片/image-20211108154405864.png