看了一遍,似乎学到不少,似乎又都忘了....
写一下自己知道的,以后学到更多再继续更新。
第一个问题为什么有哈希表:
哈希表的出现是为了应对查找排序问题,为了提升查找速度而设计的一种空间换时间的方法,所谓空间换时间就是占用较大内存但是可以加快速度,
举个例子比如动态规划算法,当使用递归进行穷举计算所有可能场景时,会有重复性的计算,当数据量特别大会造成超时内存泄露的问题,使用动态规划就可以把我们访问过的可能存储下来,当我们在这个基础上进行计算时查表就可以,这就是一个典型的空间换时间的方法,我利用一些空间来存储值,使查找时间变短。
参考这个思想就可以理解哈希表了,哈希表将针对键值key计算出哈希值用来做为存放数据的地址。类似计数排序,当有1的时候data[1]++,就是把数据1放在了键值1对应的地址上,但是当数据量特别大的时候,会出现根据键值计算出来的哈希地址冲突的问题,就好比拎着一个篮子去买菜,买的少的时候可以分开萝卜放左边白菜放右边,但是当遇到一个吃货,左买右买会发现新买的黄瓜没有地方放了,因为放蔬菜这一块地方已经有了白菜。这就冲突了,所以接下来就要想办法解决放的冲突,又要保证最根本的问题找起来快,把所有菜乱堆到一起当然放起来快,但是找起来就麻烦了。
第二个问题怎么存储数据:
我们知道最根本的是根据key算出来的地址存储value。所以存储主要是解决key算出来的地址下能够存储数据,当这个地址已经存储了数据的时候怎么办的问题。所以如果根据key算出来的值冲突了我们就要想个办法再重新计算一个值,同时要考虑的未来查找是否方便。毕竟重新计算值的方法可以有很多种。所以存储和查找实质上是一个问题。刚才分享的JDK源码分析中,按照设计的方法重新计算值以后,我们把存储的地址放在原哈希地址已经存放的数组指针上,可以根据
int hash = hash(key.hashCode());
for(Entry<k,v> e = table[indexFor(hash,table.length)];e!=null;e = e.next) {
Object k;
if(e.hash == hash && ((k=e.key)==key||key.equals(k)))
return e.value;
}
根据原hash地址数组的指针来查找key对应的数值。
这是一种方法。