1200页Java架构面试专题及答案
小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞
百度、字节、美团等大厂常见面试题
- operations will ever occur.
复制代码
翻译大概意思是:
作为一般规则,默认负载因子(0.75)在时间和空间成本上提供了良好的权衡。负载因子数值越大,空间开销越低,但是会提高查找成本(体现在大多数的HashMap类的操作,包括get和put)。设置初始大小时,应该考虑预计的entry数在map及其负载系数,并且尽量减少rehash操作的次数。如果初始容量大于最大条目数除以负载因子,rehash操作将不会发生。
简言之, 负载因子0.75 就是冲突的机会 与空间利用率权衡的最后体现,也是一个程序员实验的经验值。
这个回答解释:一个bucket空和非空的概率为0.5,通过牛顿二项式等数学计算,得到这个loadfactor的值为log(2),约等于0.693。
最后选择选择0.75,可能0.75是接近0.693的四舍五入数中,比较好理解的一个,并且默认容量大小16*0.75=12,为一个整数。
链表转换红黑树的阀值为什么是8
/**
-
The bin count threshold for using a tree rather than list for a
-
bin. Bins are converted to trees when adding an element to a
-
bin with at least this many nodes. The value must be greater
-
than 2 and should be at least 8 to mesh with assumptions in
-
tree removal about conversion back to plain bins upon
-
shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
复制代码
JDK8及以后的版本中,HashMap底层数据结构引入了红黑树。当添加元素的时候,如果桶中链表元素超过8,会自动转为红黑树。那么阀值为什么是8呢?请看HashMap的源码这段注释:
-
Ideally, under random hashCodes, the frequency of
-
nodes in bins follows a Poisson distribution
-
(http://en.wikipedia.org/wiki/Poisson_distribution) with a
-
parameter of about 0.5 on average for the default resizing
-
threshold of 0.75, although with a large variance because of
-
resizing granularity. Ignoring variance, the expected
-
occurrences of list size k are (exp(-0.5) * pow(0.5, k) /
-
factorial(k)). The first values are:
-
0: 0.60653066
-
1: 0.30326533
-
2: 0.07581633
-
3: 0.01263606
-
4: 0.00157952
-
5: 0.00015795
-
6: 0.00001316
-
7: 0.00000094
-
8: 0.00000006
-
more: less than 1 in ten million
复制代码
理想状态中,在随机哈希码情况下,对于默认0.75的加载因子,桶中节点的分布频率服从参数为0.5的泊松分布,即使粒度调整会产生较大方差。
由对照表,可以看到链表中元素个数为8时的概率非常非常小了,所以链表转换红黑树的阀值选择了8。
一个树的链表还原阈值为什么是6
/**
-
The bin count threshold for untreeifying a (split) bin during a
-
resize operation. Should be less than TREEIFY_THRESHOLD, and at
-
most 6 to mesh with shrinkage detection under removal.
*/
static final int UNTREEIFY_THRESHOLD = 6;
复制代码
上一小节分析,可以知道,链表树化阀值是8,那么树还原为链表为什么是6而不是7呢?这是为了防止链表和树之间频繁的转换。如果是7的话,假设一个HashMap不停的插入、删除元素,链表个数一直在8左右徘徊,就会频繁树转链表、链表转树,效率非常低下。
最大容量为什么是1 << 30
/**
-
The maximum capacity, used if a higher value is implicitly specified
-
by either of the constructors with arguments.
-
MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
复制代码
HashMap为什么要满足2的n次方?
由第一小节(HashMap默认初始化大小为什么是1 << 4)分析可知,HashMap容量需要满足2的幂,与运算比取余运算效率高。只有容量是2的n次方时,与运算才等于取余运算。
tab[i = (n - 1) & hash]
复制代码
为什么不是2的31次方呢?
我们知道,int占四个字节,一个字节占8位,所以是32位整型,也就是说最多32位。那按理说,最大数可以向左移动31位即2的31次幂,在这里为什么不是2的31次方呢?
实际上,二进制数的最左边那一位是符号位,用来表示正负的,我们来看一下demo代码:
System.out.println(1<<30);
System.out.println(1<<31);
System.out.println(1<<32);
System.out.println(1<<33);
System.out.println(1<<34);
复制代码
输出:
1073741824
-2147483648
1
2
4
复制代码
所以,HashMap最大容量是1 << 30。
哈希表的最小树形化容量为什么是64
最后
既已说到spring cloud alibaba,那对于整个微服务架构,如果想要进一步地向上提升自己,到底应该掌握哪些核心技能呢?
就个人而言,对于整个微服务架构,像RPC、Dubbo、Spring Boot、Spring Cloud Alibaba、Docker、kubernetes、Spring Cloud Netflix、Service Mesh等这些都是最最核心的知识,架构师必经之路!下图,是自绘的微服务架构路线体系大纲,如果有还不知道自己该掌握些啥技术的朋友,可根据小编手绘的大纲进行一个参考。
如果觉得图片不够清晰,也可来找小编分享原件的xmind文档!
且除此份微服务体系大纲外,我也有整理与其每个专题核心知识点对应的最强学习笔记:
-
出神入化——SpringCloudAlibaba.pdf
-
SpringCloud微服务架构笔记(一).pdf
-
SpringCloud微服务架构笔记(二).pdf
-
SpringCloud微服务架构笔记(三).pdf
-
SpringCloud微服务架构笔记(四).pdf
-
Dubbo框架RPC实现原理.pdf
-
Dubbo最新全面深度解读.pdf
-
Spring Boot学习教程.pdf
-
SpringBoo核心宝典.pdf
-
第一本Docker书-完整版.pdf
-
使用SpringCloud和Docker实战微服务.pdf
-
K8S(kubernetes)学习指南.pdf
另外,如果不知道从何下手开始学习呢,小编这边也有对每个微服务的核心知识点手绘了其对应的知识架构体系大纲,不过全是导出的xmind文件,全部的源文件也都在此!
714900806417)]
另外,如果不知道从何下手开始学习呢,小编这边也有对每个微服务的核心知识点手绘了其对应的知识架构体系大纲,不过全是导出的xmind文件,全部的源文件也都在此!
[外链图片转存中…(img-Rf4XzZu2-1714900806418)]