谈谈你对HashMap中put/get方法的认识?如果了解再谈谈HashMap的扩容机制?默认大小是多少?什么是加载因子(或填充比)?什么是吞吐临界值(或阈值、threshold)?

谈谈你对HashMap中put/get方法的认识?如果了解再谈谈HashMap的扩容机制?默认大小是多少?什么是加载因子(或填充比)?什么是吞吐临界值(或阈值、threshold)?_第1张图片

jdk7的文字描述(会在中间介绍一些8的改变):

  • 将key1,value1(就是一个键值对Entry)添加到数组中,首先根据key1所在累的hashCode()方法计算key1的哈希值1,然后使用某种算法,得到哈希值2,(个人理解是两次计算哈希值是为了让得到的哈希值相同的概率更小些),哈希值2在使用indexFor()
    方法得到底层table数组中存放的位置:index(0<=index &&index <= 15);
    【1.在jdk8中,当使用了空参构造器创建对象时,底层并没有创建长度为16的数组,2.而是当我们首次调用put()函数时底层才会首先创建长度为16的数组,3.底层创建的数组为:Node[](classNode implements Map.Entry{},这里与jdk7有所不同】

  • 如果index位置没有元素,则直接把key1,value1这个键值对添加进去(添加成功1)

  • 如果index位置有元素(key2,value2)【我在这里只考虑只存在一对键值对,实际上是会存在多个键值对的,对应的把多个键值对考虑进来就好】,则比较key1和key2的哈希值。

--------------如果两者的哈希值不同,则(key1,value1)添加成功 (添加成功2)

--------------如果两者的哈希值相同,则调用key1所在类的equals() ,将key作为参数传递到字方法中,比较两个key是否相等;
--------------------------如果返回false,则(key1,value1)添加成功 (添加成功3)
【在jdk8中,当某个索引位置上的链表长度大于8,且数组总长度大于64是,将此索引上的元素修改为使用红黑数进行存储(这样会大大提高效率),在形成链表时,新添加的元素在链表的结尾,而jdk7是头插法】
------------------------如果返回true,则value1替换原有的key2对应value2 (修改成功)

谈谈你对HashMap中put/get方法的认识?如果了解再谈谈HashMap的扩容机制?默认大小是多少?什么是加载因子(或填充比)?什么是吞吐临界值(或阈值、threshold)?_第2张图片
说明:

	添加成功1:将key1,value1存放在数组的位置上;
	添加成功2和3:将key1,value1添加在链表上,jdk7是存放在链表头部(jdk8则是尾部)			

对于扩容:当添加的数据达到临界值(数组的长度加载因子)时,则进行扩容,默认扩容为原来的两倍,默认的临界值为:160.75=12,默认的加载因子是0.75;

对于加载因子:

  • 负载因子的大小决定了HashMap的数据密度。
  • 负载因子越大密度越大,发生碰撞的几率越高,数组中的链表越容易长,造成查询或插入时的比较次数增多,性能会下降。
  • 负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建议初始化预设大一点的空间
  • 按照其他语言的参考及研究经验,会考虑将负载因子设置为0.7~0.75,此时平均检索长度接近于常数。

你可能感兴趣的:(java高级)