1.hashmap的底层数据结构1.8之前和1.8的区别?
JDK1.7的时候使用的是数组+ 单链表的数据结构.但是在JDK1.8及之后时,使用的是数组+链表+红黑树的数据结构(当链表的深度达到8的时候,也就是默认阈值,就会自动扩容把链表转成红黑树的数据结构)
2.为什么转换成红黑树的节点是8
由于treenodes的大小大约是常规节点的两倍,因此我们仅在容器包含足够的节点以保证使用时才使用它们,当它们变得太小(由于移除或调整大小)时,它们会被转换回普通的node节点,容器中节点分布在hash桶中的频率遵循泊松分布,桶的长度超过8的概率非常非常小。所以作者应该是根据概率统计而选择了8作为阀值
//Java中解释的原因
* Because TreeNodes are about twice the size of regular nodes, we
* use them only when bins contain enough nodes to warrant use
* (see TREEIFY_THRESHOLD). And when they become too small (due to
* removal or resizing) they are converted back to plain bins. In
* usages with well-distributed user hashCodes, tree bins are
* rarely used. 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
3.hashMap 加载因子为什么0.75
我们都知道如果需要扩容,就会去申请内存空间,然后把原桶的元素复制到新桶中,这是一个相对比较耗时的操作,如果我们设置的太大就会浪费内存空间,同时也增加了查询的成本。相反加载因子过低,虽然可以减少查询时间成本,但是空间利用率低,同时也增加了rehash的次数。所以一般使用HashMap时建议根据场景去预估初始容量,减少扩容操作。
其实作为一个通用规则,写HashMap源码的人只是做了一个很好的折中方案,提供了一个很好的权衡,完全是时间和空间成本上的一个折中选择,还有就是如果设置大了哈希冲突率越大,因此必须在冲突、空间利用率、性能上找一个折中方案!
4.hashmap存储元素的过程
先根据key的hashcode值计算出hash值,然后用这个哈希值确定在数组中的位置,
再把value值放进去,如果这个位置本来没放东西,就会直接放进去,如果之前就有,就会生成一个链表,
把新放入的值放在头部,当用get方法取值时,会先根据key的hashcode值计算出hash值,确定位置,再根据equals方法从该位置上的链表中取出该value值,
5.hashmap的构造函数哪些?
1.无参构造函数。
2.设置初始容量的构造函数
3.设置初始容量和负载因子的构造函数
4.以Map进行初始化的构造函数
Aop整合日志流程
第一步:引入相关依赖
第二步:创建测试Controller
第三步:创建切面类以及前置和后置
第四步:测试