个人关于hashmap的一些总结

1、map以key-value形式存储数据。map的实现形式有hashmap,treemap,linkedhashmap等。

hashmap:map基于散列表实现,存储键值顺序和插入次序无关,优势在于查询速度快。

treemap:放入treemap中的值会根据key按照字母顺序排序,与插入顺序无关

linkedhashmap:类似于hashmap,查询速度稍慢,但迭代遍历速度快,存储值得顺序和插入顺序一致。

2、hashmap为什么具有查询速度优势?

这和hashmap存储数值的方式有关。hashmap以散列形式存储元素,hashmap用通过object的hashcode()方法

生成散列码(默认用对象的地址计算散列码)。

这里引入一个桶位的概念,即hashmap用来存储键值对的数组。每次调用hashmap的put(K,V)方法存放元素时,

会首先用键对象的hashcode()方法来生成一个散列码,把这个散列码作为数组的下标,把键值对一块存储在对应的桶位,

每个桶位以链表的形式保存键值对。这是为什么呢?由于不同的对象可能生成相同的散列码,即不同的对象存储在

扫描二维码关注公众号,回复: 2988364 查看本文章

同一个桶位,这时后来的对象就要插入到链表的尾部。

查找时使用get(K)方法,根据键对象生成的hashcode快速定位到桶位,再用keys.equals()方法线性遍历对应key

3、覆盖hashcode()方法

hashmap默认使用的是对象的地址计算散列码,如果想要使用别的方式计算散列码,就得重写hashcode方法,

如string对象就是用string的内容计算散列码的。用来计算散列码的值不应该是易变得,否则put()和get()前后得到的

hashcode不一致,无法查询到。

4、如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

负载因子是桶中实际存储的对象数量和最大容量的比值。默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置

5、为什么String, Interger这样的wrapper类适合作为键?

String, Interger这样的wrapper类作为HashMap的键是再适合不过了,而且String最为常用。因为String是不可变的,也是final的,而且已经重写了equals()和hashCode()方法了。其他的wrapper类也有这个特点。不可变性是必要的,因为为了要计算hashCode(),就要防止键值改变,如果键值在放入时和获取时返回不同的hashcode的话,那么就不能从HashMap中找到你想要的对象。不可变性还有其他的优点如线程安全。如果你可以仅仅通过将某个field声明成final就能保证hashCode是不变的,那么请这么做吧。因为获取对象的时候要用到equals()和hashCode()方法,那么键对象正确的重写这两个方法是非常重要的。如果两个不相等的对象返回不同的hashcode的话,那么碰撞的几率就会小些,这样就能提高HashMap的性能。

猜你喜欢

转载自blog.csdn.net/goudu7509/article/details/81258945