大数据之什么是Hash表

大数据
大数据之什么是Hash表,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙。

大数据之什么是Hash表,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙。

[[278251]]

1.散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。

也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。比如我们存储70个元素,但我们可能为这70个元素申请了100个元素的空间。70/100=0.7,这个数字称为负载(加载)因子。我们之所以这样做,也 是为了“快速存取”的目的。我们基于一种结果尽可能随机平均分布的固定函数H为每个元素安排存储位置,以达到快速存取。但是由于此随机性,也必然导致一个问题就是冲突。所谓冲突,即两个元素通过散列函数H得到的地址相同,那么这两个元素称为“同义词”。这类似于70个人去一个有100个椅子的饭店吃饭。散列函数的计算结果是一个存储单位地址,每个存储单位称为“桶”。设一个散列表有m个桶,则散列函数的值域应为[0,m-1]。

这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置

2.hash表扩容的理解

可是当哈希表接近装满时,因为数组的扩容问题,性能较低(转移到更大的哈希表中).

Java默认的散列单元大小全部都是2的幂,初始值为16(2的4次幂)。假如16条链表中的75%链接有数据的时候,则认为加载因子达到默认的0.75。HahSet开始重新散列,也就是将原来的散列结构全部抛弃,重新开辟一个散列单元大小为32(2的5次幂)的散列结果,并重新计算各个数据的存储位置。以此类推下去.....

负载(加载)因子:0.75.-->hash表提供的空间是16 也就是说当到达12的时候就扩容

3.排重机制的实现

假如我们有一个数据(散列码76268),而此时的HashSet有128个散列单元,那么这个数据将有可能插入到数组的第108个链表中(76268%128=108)。但这只是有可能,如果在第108号链表中发现有一个老数据与新数据equals()=true的话,这个新数据将被视为已经加入,而不再重复丢入链表。

4.优点

哈希表的插入和查找是很优秀的.

对于查找:直接根据数据的散列码和散列表的数组大小计算除余后,就得到了所在数组的位置,然后再查找链表中是否有这个数据即可。因为数组本身查找速度快,所以查找的效率高低体现在链表中,但是真实情况下在一条链表中的数据又很少,有的甚至没有,所以几乎没有什么迭代的代价。所以散列表的查找效率建立在散列单元所指向的链表中数据的多少上.

对于插入:数组的插入速度慢,而链表的插入速度快.当我们使用哈希表时,不需要更改数组的结构,只需要在找到对应的数组下标后,进入对应的链表,操作链表即可.所以hash表的整体插入速度也很快.

5.模拟实现代码

Node类

 

  1. public class Node { 
  2. // key、value模拟键值对的数据 
  3.     public Integer key
  4.     public String value; 
  5.     // 下一节点的引用 
  6.     public Node next
  7.     public Node() { 
  8.     } 
  9.     public Node(int key, String value) { 
  10.         this.key = key
  11.         this.value = value; 
  12.     } 
  13.   

MyLinkedList类

 

  1.  public class MyLinkedList { 
  2.     // 根节点 
  3.     private Node root; 
  4.   
  5.     public MyLinkedList() { 
  6.         root = new Node(); 
  7.     } 
  8.     /** 
  9.      * 添加数据,key值必须唯一,如果重复值将被覆盖 
  10.      * @param key 
  11.      */ 
  12.     public void add(int key, String value) { 
  13.   
  14.         Node newNode = new Node(key, value); 
  15.         Node current = root; 
  16.         while (current.next != null) { 
  17.             if(current.next.key == key) { 
  18.                 current.next.value = value; 
  19.                 return
  20.             } 
  21.             current = current.next
  22.         } 
  23.         current.next = newNode; 
  24.     } 
  25.   
  26.     /** 
  27.      * 删除数据 
  28.      * @param key 
  29.      * @return 
  30.      */ 
  31.     public boolean delete(int key) { 
  32.   
  33.         Node current = root; 
  34.         while (current.next != null) { 
  35.             if(current.next.key == key) { 
  36.                 current.next = current.next.next
  37.                 return true
  38.             } 
  39.             current = current.next
  40.         } 
  41.         return false
  42.     } 
  43.   
  44.     /** 
  45.      * 根据key获取value 
  46.      * @param key 
  47.      * @return 
  48.      */ 
  49.     public String get(int key) { 
  50.   
  51.         Node current = root; 
  52.         while (current.next != null) { 
  53.             if(current.next.key == key) { 
  54.                 return current.next.value; 
  55.             } 
  56.             current = current.next
  57.         } 
  58.         return null
  59.     } 
  60.   
  61.     /** 
  62.      * 遍历链表,列出所有数据 
  63.      * @return 
  64.      */ 
  65.     public String list() { 
  66.   
  67.         String str = ""
  68.         Node current = root.next
  69.         while (current != null) { 
  70.             str += "(" + current.key + "," + current.value + "),"
  71.             current = current.next
  72.         } 
  73.         return str; 
  74.     } 
  75.   
  76.     @Override 
  77.     public String toString() { 
  78.         return list(); 
  79.     } 

MyHashMap类

 

  1. // 哈希表 
  2. public class MyHashMap { 
  3.   
  4.     // 链表数组,数组的每一项都是一个链表 
  5.     private MyLinkedList[] arr; 
  6.     // 数组的大小 
  7.     private int maxSize; 
  8.   
  9.     /** 
  10.      * 空参构造,默认数组大小为10 
  11.      */ 
  12.     public MyHashMap() { 
  13.         maxSize = 10; 
  14.         arr = new MyLinkedList[maxSize]; 
  15.     } 
  16.   
  17.     /** 
  18.      * 带参构造,数组大小自定义 
  19.      * @param maxSize 
  20.      */ 
  21.     public MyHashMap(int maxSize) { 
  22.         this.maxSize = maxSize; 
  23.         arr = new MyLinkedList[maxSize]; 
  24.     } 
  25.   
  26.     /** 
  27.      * 添加数据,key值必须唯一 
  28.      * @param key 
  29.      * @param value 
  30.      */ 
  31.     public void put(int key, String value) { 
  32.   
  33.         int index = getHashIndex(key); 
  34.         if(arr[index] == null) { 
  35.             arr[index] = new MyLinkedList(); 
  36.         } 
  37.         arr[index].add(key, value); 
  38.     } 
  39.   
  40.     /** 
  41.      * 删除数据 
  42.      * @param key 
  43.      * @return 
  44.      */ 
  45.     public boolean delete(int key) { 
  46.   
  47.         int index = getHashIndex(key); 
  48.         if(arr[index] != null) { 
  49.             return arr[index].delete(key); 
  50.         } 
  51.         return false
  52.     } 
  53.   
  54.     /** 
  55.      * 根据key获取value 
  56.      * @param key 
  57.      * @return 
  58.      */ 
  59.     public String get(int key) { 
  60.   
  61.         int index = getHashIndex(key); 
  62.         if(arr[index] != null) { 
  63.             return arr[index].get(key); 
  64.         } 
  65.         return null
  66.     } 
  67.   
  68.     /** 
  69.      * 获取数组下标 
  70.      * @param key 
  71.      * @return 
  72.      */ 
  73.     private int getHashIndex(Integer key) { 
  74.         return key.hashCode() % maxSize; 
  75.     } 
  76.   
  77.     /** 
  78.      * 遍历数组中所有链表的数据 
  79.      * @return 
  80.      */ 
  81.     public String list() { 
  82.   
  83.         String str = "[ "
  84.         for (int i = 0; i < maxSize; i++) { 
  85.             if(arr[i] != null) { 
  86.                 str += arr[i].toString(); 
  87.             } 
  88.         } 
  89.         str = str.substring(0, str.length()-1); 
  90.         str += " ]"
  91.         return str; 
  92.     } 
  93.   
  94.     @Override 
  95.     public String toString() { 
  96.         return list(); 
  97.     } 

测试类

 

  1. public class Test { 
  2.   
  3.     public static void main(String[] args) { 
  4.   
  5.         MyHashMap map = new MyHashMap(20); 
  6.   
  7.         map.put(5, "aaa"); 
  8.         map.put(8, "bbb"); 
  9.         map.put(3, "ccc"); 
  10.         map.put(8, "bbb"); 
  11.         map.put(2, "ddd"); 
  12.         map.put(9, "eee"); 
  13.   
  14.         System.out.println(map); 
  15.         System.out.println(map.get(3)); 
  16.         System.out.println(map.delete(2)); 
  17.         System.out.println(map); 
  18.     } 

 

责任编辑:未丽燕 来源: 阿里云栖社区
相关推荐

2019-03-22 13:53:07

大数据架构数据源数据质量

2015-01-27 14:36:18

2016-12-12 16:31:46

大数据决策

2017-12-19 21:29:58

物联网区块链大数据

2018-06-25 11:20:18

LinuxPython大数据

2013-11-12 10:50:02

大数据时代大数据

2024-11-07 08:47:53

2021-04-15 09:37:05

大数据Maven

2021-09-29 16:39:23

大数据存储

2022-02-27 15:28:53

大数据挑战战略

2020-12-02 10:32:10

大数据存储

2019-07-10 13:02:12

大数据智慧城市数据安全

2021-04-29 10:08:10

数据结构哈希表

2015-03-04 11:01:36

大数据数据分析分析

2015-07-29 16:19:54

大数据时代分析

2017-04-06 09:35:10

大数据SparkSQLSpark

2018-11-05 15:15:38

大数据流式数据互联网

2015-04-23 16:06:05

大数据

2016-08-16 00:52:19

大数据互联网

2019-10-31 15:49:10

大数据专家共生关系
点赞
收藏

51CTO技术栈公众号