基础知识记录
Hash 函数
hash 也称散列,哈希。基本原理是将任意长度的输入,通过 hash 函数变成固定长度的输出。原始数据映射后的二进制串就是哈希值
Hash 表
hash 表是一个存储键值映射的数据结构,它的读写效率在装载因子在正常水平时为 O(1),若不正常时为 O(n)。它有两种实现方案; 开放寻址法:底层数据结构为数组,在发生 hash 冲突时,从索引(index=hash(key)%array.length
)位置开始向后查找为空的位置进行插入,查询也是同理。拉链法:底层数据结构为数组加链表,当 hash 发生冲突时,会在冲突位置上进行链表遍历查找,如果找到就替换,没找到就链表后面插入,索引计算方式相同。两种方式相比而言后者查找长度更短,内存为动态分配,还可以用红黑树进行优化链表。
Go 语言中的 map 也是利用 hash 表来实现的,其中底层结构中 hmap
表示哈希表。有几个关键的字段 count
表示的是元素的数量,B
表示桶(存放的是链表(bmap
)结构)的个数,且桶的个数是 2的 n 次方的倍数,还有 hash0
表示计算 hash 值用到的种子。在一个桶中存放的是键值对为 8 个当超过这个个数时,还有一个专门存放溢出的 key/value 的结构。当装载因子超过 6.5 或哈希表使用了太多溢出桶,map 要进行扩容处理,扩容中会有 oldbuckets
保存之前的数据。会有等量扩容和倍数扩容。此时如果有增删改操作,发生时,原来的桶不会立即删除,还会使用之前桶里的数据等所有操作结束后在进行正确的操作。在 map 进行字面量赋值时,没超过 25 时,会将所有的键值对放到 map 中,超过会遍历将其放到 map 中。在向 map 插入值时,会使用 bmap
中存储的 hash 值的高8 位进行加速匹配查找,对应的 key 以便找到对应的值。删除也是利用这个原理。
bit byte
bit(位) 是计算机最小的存储和发送接收单元,也就是二进制中的位,每一位上的数字为 0 或 1 使用进位制来表示数字。一位有两种组合方式 0 或 1,两位有 4 种组合方式 00 01 10 11 分别代表了数字 0 1 2 3 所以位可以表示成 2 的指数增长方式及 2 的 n 次方。所表示的数字是 0 ~ 2^n -1 因为是从 0 开始的。
8 bits(位)等于 1 byte(字节),可以用它来存储字符和字母,因为它表示数字的范围在 0 ~ 255 而 ASCLL 码在这个范围内。ASCLL 编码是将键盘的每个字符用一个数字进行代替。UNICODE 是一些语言的编码方式,通常每两个字节代表一个字符。
byte 是信息存储的最小单元,一个字母表示一个字节。
换算关系:
1KB=2^10 bytes (1024 字节)
1MB= 2^20 bytes
1GB=2^30 bytes
1TB=2^40 bytes
在网络中说到的带宽指的是 bit ,网速说的是 Byte。换算关系为带宽除以 8 约等于网速,因为存在其他因素的影响。
进制转换
计算机中的常用的进制表示为二进制,八进制,十进制和十六进制。二进制表示为0和1,逢2进1;八进制表示为07,逢8进1;十六进制表示为09,A-F(10~15),逢16进1。
符号对应的进制:
b:二进制
d:十进制
o:八进制
x:十六进制
以十进制为参考,转换方式如下:
乘法
100(二进制) = (2^2 x 1)+(2^1 x 0)+(2^0 x 0) (十进制)
100(八进制) = (8^2 x 1)+(8^1 x 0)+(8^0 x 0) (十进制)
100(十六进制) = (16^2 x 1)+(16^1 x 0)+(16^0 x 0) (十进制)
除法(将余数倒写表示最终结果)
100(十进制) = 1100100(二进制)
转换过程:
(100/2 = 50 … 0)
(50/2 = 25 … 0)
(25/2 = 12 … 1)
(12/2 = 6 … 0)
(6/2 = 3 … 0)
(3/2 = 1 … 1)
(1/2 = 0 … 1)
同理可得
100(十进制) = 144(八进制)
100(十进制) = 64(十六进制)
八进制,十六进制与二进制之间的转换:
八进制中的一位相当于二进制中的三位(2^3=8)
十六进制中的一位相当于二进制中的四位(2^4=8)
1001(二进制) = 11(八进制 [从低位开始转换,高位不足用0表示])
1001(二进制) = a(十六进制 [从低位开始转换,高位不足用0表示])
可以将其转为十进制在进行转换
回调函数
回调表现状态为当编写的库函数需要你传入的函数作为参数才能实现某种功能的时候,中间函数就使用到了你编写的函数,而这个过程就称为回调。
在这个机制中存在三个个体,主调者,中间者,被调用者。它们分别对应了主函数,中间函数(库函数),回调函数(传入中间函数参数的函数)。
回调函数在前端中为异步处理的方案。当一些耗时操作完成在执行回调里面的内容!在异步处理中使用回调会有一个问题就是回调地域。比如一个网络请求依赖另一个网络请求的结果!
前端异步
在使用回调函数进行异步操作会产生回调地域的问题,所以在 ES6 使用 Promise 来解决这个问题,对象有三个状态:pending(初始状态), fulfilled(resolve 完成状态),rejected(失败状态),
pending可以转化为fulfilled或rejected并且只能转化一次,也就是说如果pending转化到fulfilled状态,那么就不能再转化到rejected。并且fulfilled和rejected状态只能由pending转化而来,两者之间不能互相转换。
缓存
建立缓存的方式:HashMap
,Redis
。
Session 和 Cookie
cookie 是 web 应用中客户端(一般指浏览器)存储用户信息的方式,存在浏览器会存在一定的风险,所以可以使用 session 也就是在服务器保存用户的信息。请求时只用带上 sessionID
便可以找到对应的信息,可以将 session 存在文件,内存或数据库中。
Shell 中的 Source
source 是 shell 的内置命令,用来在当前 shell 环境(用户当前敲命令的终端)下执行某文件中的一组命令,可以简写为点(.)。
获取 shell 脚本(.sh)文件的路径和文件名可以在脚本文件中使用 $BASH_SOURCE
变量。
#!/bin/bash
echo "shell file position: $BASH_SOURCE"
用户级线程、内核级线程
内核级线程就是操作系统调用的线程,而用户级线程是抽象出来给用户操作的一个线程。它和内核级线程是绑定关系,它对操作系统而言是不可见的。
统一资源标识符格式
[协议名]://[用户名]:[密码]@[主机名]:[端口]/[路径]?[查询参数]#[片段ID]
字节序
字节序,或字节顺序(”Endian”、”endianness” 或 “byte-order”),描述了计算机如何组织字节,组成对应的数字。
大端序:高位存在低地址(网络字节序已经为标准)
小端序:高位存在高地址(cpu中)
参考: