当前位置:   article > 正文

Java 哈希表_java哈希表怎么用

java哈希表怎么用

目录

1.概念

1.1 原理

1.2 哈希函数

1.3 冲突-解决-负载因子

2.哈希表的实现

2.1 定义节点类以及字段

2.2 新增元素

2.3 获取与key对应的value值

2.4 总代码


1.概念

1.1 原理

哈希表是一种时间复杂度只有O(1)的查找数据结构

原理(个人理解):取出一块内存,将插入的数据按照某种函数(哈希函数)去计算,得到一个内存地址,然后将数据存放到该地址,再取出时,可以根据这个函数直接找到该地址的数据

哈希表的难点主要为以下两点:

(1)设计哈希函数

(2)解决哈希冲突

1.2 哈希函数

一个好的哈希表,一定要对应一个好的哈希函数.

哈希函数的设置主要遵循以下几个条件:

(1)函数的结果要在可取空间范围内,并且计算的结果可以取到空间内的任意一块地址

(2)哈希函数计算出来的地址应均匀分布在空间内

常用的哈希函数:

(1)直接定制法: 比如 hash = A*key + B

(2)除留余数法:比如 hash = key % M(M要小于最大可取空间)

1.3 冲突-解决-负载因子

无论哈希函数设计的多么巧妙,发生冲突也是不可避免的(同一块地址,有两个数据符合),这个时候就要去解决冲突.

解决冲突的方法主要为闭散列开散列

闭散列的方法为:

将冲突的元素放在其解析地址的后一个地址,或者通过一个函数去进行二次计算,相对于开散列比较简单

我们这里主要描述 开散列 也是java库中的使用方法

开散列(也叫链地址法):

将每块地址都设置成一个链表,当发生冲突时,将其进行 头插或者尾插 用来解决冲突问题

但是这样会导致效率的下降,所以需要不断的去扩容调节数组的容量(用数组实现的哈希表)

我们设置一个负载因子n,n = 存储数据个数/数组长度

假设我们设置的负载因子峰值为0.75,那么当实际的计算结果高于这个峰值时就要进行扩容操作,降低冲突发生的概率

2.哈希表的实现

2.1 定义节点类以及字段

  1. private static class Node {
  2. private int key;
  3. private int value;
  4. Node next;
  5. public Node(int key, int value) {
  6. this.key = key;
  7. this.value = value;
  8. }
  9. }
  10. private Node[] array;
  11. private int size; // 当前的数据个数
  12. private static final double LOAD_FACTOR = 0.75;//负载因子最大值
  13. private static final int DEFAULT_SIZE = 8;//默认桶的大小
  14. public HashBucket() {
  15. array = new Node[DEFAULT_SIZE];
  16. }

2.2 新增元素

这里使用的哈希函数方法为除留余数法.

新增/更新:

首先通过哈希函数找到与插入元素相匹配的链表

然后查找该链表中是否有与插入的节点的key相同的节点,如果有则只更新该节点的values值

若没有相同的key,则进行下一步,将新节点用头插法插入该链表

最后对哈希表进行负载因子的判断,如果表中的负载因子大于设置的最大值,则对链表进行扩容.

扩容:

首先创建一个新的节点数组,长度为原数组的2倍

然后将原数组的每个节点,重新插入新数组

最后将新数组赋给原数组

  1. //新增
  2. public void put(int key, int value) {
  3. int index = key % array.length;
  4. Node cur = array[index];
  5. while(cur != null) {
  6. if(cur.key == key) {
  7. cur.value = value;
  8. return;
  9. }
  10. cur = cur.next;
  11. }
  12. Node node = new Node(key,value);
  13. node.next = array[index];
  14. array[index] = node;
  15. size++;
  16. if(loadFactor() >= 0.75) {
  17. resize();
  18. }
  19. }
  20. //判断负载因子是否 达到/超过 最大值
  21. private double loadFactor() {
  22. return size * 1.0 / array.length;
  23. }
  24. //扩容
  25. private void resize() {
  26. Node[] newArray = new Node[array.length * 2];
  27. for(int i = 0;i < array.length;i++) {
  28. Node cur = array[i];
  29. while(cur != null) {
  30. Node curNext = cur.next;
  31. int index = cur.key % newArray.length;
  32. cur.next = newArray[index];
  33. newArray[index] = cur;
  34. cur = curNext;
  35. }
  36. }
  37. array = newArray;
  38. }

2.3 获取与key对应的value值

首先用哈希函数对key进行判断,找到相对应的链表

然后寻找与key相对应的节点,最后返回value

如果没有则返回-1

  1. public int get(int key) {
  2. int index = key % array.length;
  3. Node cur = array[index];
  4. while(cur != null) {
  5. if(cur.key == key) {
  6. return cur.value;
  7. }
  8. cur = cur.next;
  9. }
  10. return -1;
  11. }

2.4 总代码

  1. public class HashBucket {
  2. private static class Node {
  3. private int key;
  4. private int value;
  5. Node next;
  6. public Node(int key, int value) {
  7. this.key = key;
  8. this.value = value;
  9. }
  10. }
  11. private Node[] array;
  12. private int size; // 当前的数据个数
  13. private static final double LOAD_FACTOR = 0.75;
  14. private static final int DEFAULT_SIZE = 8;//默认桶的大小
  15. public HashBucket() {
  16. array = new Node[DEFAULT_SIZE];
  17. }
  18. public void put(int key, int value) {
  19. int index = key % array.length;
  20. Node cur = array[index];
  21. while(cur != null) {
  22. if(cur.key == key) {
  23. cur.value = value;
  24. return;
  25. }
  26. cur = cur.next;
  27. }
  28. Node node = new Node(key,value);
  29. node.next = array[index];
  30. array[index] = node;
  31. size++;
  32. if(loadFactor() >= 0.75) {
  33. resize();
  34. }
  35. }
  36. //扩容
  37. private void resize() {
  38. Node[] newArray = new Node[array.length * 2];
  39. for(int i = 0;i < array.length;i++) {
  40. Node cur = array[i];
  41. while(cur != null) {
  42. Node curNext = cur.next;
  43. int index = cur.key % newArray.length;
  44. cur.next = newArray[index];
  45. newArray[index] = cur;
  46. cur = curNext;
  47. }
  48. }
  49. array = newArray;
  50. }
  51. private double loadFactor() {
  52. return size * 1.0 / array.length;
  53. }
  54. public int get(int key) {
  55. int index = key % array.length;
  56. Node cur = array[index];
  57. while(cur != null) {
  58. if(cur.key == key) {
  59. return cur.value;
  60. }
  61. cur = cur.next;
  62. }
  63. return -1;
  64. }
  65. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/440219
推荐阅读
相关标签
  

闽ICP备14008679号