Hash表:
1、hash表就是通过hash函数将需要保存在hash表中的key值翻译成hash bucket(也就是hash数组,是一个按照序列的数组)。然后查询时候也是通过hash函数计算出bucket的index值,也就是计算出可以在hash桶的第几个位置,这样就能通过访问数组的方式直接访问到需要值,bucket上记录index对应的key值。但是存在一个问题就是可能存在多个key计算出来的bucket index值相同,这样就叫hash冲突,解决hash冲突的办法有两个:一个是如果先hash. bucket被占用,则顺序遍历数组,找到一个非占用的bucket来存key值。查询时候就需要从index向下遍历。这种方式还存在林一个问题就是删除bucket,这样就存在bucket空洞,因为在查询冲突的bucket是通过遍历并判断bucket不被占用处理的。因此删除bucket时候需要在对应的bucket上记录这个位置下面还需要继续遍历。同时因为一旦冲突就需要把数据放在数组的其他bucket上,因此bucket很有可能被快速用完,这样导致hash数组放不下,需要扩容。
林一个方式在bucket后面通过挂链表的方式解决冲突。这样冲突节点的掺入和删除还是挺快的。但是查询节点需要遍历链表。这样也窜爱一个问题,就是链表节点过多导致查询效率低,所以为了解决查询问题,buckdet 后面可以接二叉搜索树,但是二叉搜索树在最坏情况下会变成一个链表,所以需要一颗平衡二叉搜索树,因此这里 一般就整出了红黑树(二叉树,平衡,搜索二叉树)。进一步优化就是冲突节点小的时候使用链表,节点多了就变成红黑树,节点少了又变回链表。
2、hash表的问题:
2.1、不能存大量的数据
2.2、线程不安全
2.3、扩容会有空间操作,不支持多线程
3、设计hash表需要注意的事情:
1、优秀的hash函数,冲突小
2、空间 //空间换时间,内存不能太大
3、性能 增删查找要快, //具备算法和数据结构的思维
4、扩容
5、hash 冲突怎么解决。
6、高并发
hash索引不能进行范围查找,所以,不能处理范围查找的场景。所以就衍生出了B树,B+数的,可以解决范围查找的问题。