好程式設計師大資料學習路線分享什麼是Hash表
好程式設計師大資料學習路線分享 什麼是Hash 表,Hash ,一般翻譯做“雜湊”,也有直接音譯為“雜湊”的,它是基於快速存取的角度設計的,也是一種典型的“空間換時間”的做法。顧名思義,該資料結構可以理解為一個線性表,但是其中的元素不是緊密排列的,而是可能存在空隙。
雜湊表( 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 類
```
public class Node {
// key、value模擬鍵值對的資料
public Integer key;
public String value;
// 下一節點的引用
public Node next;
public Node() {
}
public Node(int key, String value) {
this.key = key;
this.value = value;
}
}
```
MyLinkedList 類
```
public class MyLinkedList {
// 根節點
private Node root;
public MyLinkedList() {
root = new Node();
}
/**
* 新增資料,key值必須唯一,如果重複值將被覆蓋
* @param key
*/
public void add(int key, String value) {
Node newNode = new Node(key, value);
Node current = root;
while (current.next != null) {
if(current.next.key == key) {
current.next.value = value;
return;
}
current = current.next;
}
current.next = newNode;
}
/**
* 刪除資料
* @param key
* @return
*/
public boolean delete(int key) {
Node current = root;
while (current.next != null) {
if(current.next.key == key) {
current.next = current.next.next;
return true;
}
current = current.next;
}
return false;
}
/**
* 根據key獲取value
* @param key
* @return
*/
public String get(int key) {
Node current = root;
while (current.next != null) {
if(current.next.key == key) {
return current.next.value;
}
current = current.next;
}
return null;
}
/**
* 遍歷連結串列,列出所有資料
* @return
*/
public String list() {
String str = "";
Node current = root.next;
while (current != null) {
str += "(" + current.key + "," + current.value + "),";
current = current.next;
}
return str;
}
@Override
public String toString() {
return list();
}
}
```
MyHashMap 類
```
// 雜湊表
public class MyHashMap {
// 連結串列陣列,陣列的每一項都是一個連結串列
private MyLinkedList[] arr;
// 陣列的大小
private int maxSize;
/**
* 空參構造,預設陣列大小為10
*/
public MyHashMap() {
maxSize = 10;
arr = new MyLinkedList[maxSize];
}
/**
* 帶參構造,陣列大小自定義
* @param maxSize
*/
public MyHashMap(int maxSize) {
this.maxSize = maxSize;
arr = new MyLinkedList[maxSize];
}
/**
* 新增資料,key值必須唯一
* @param key
* @param value
*/
public void put(int key, String value) {
int index = getHashIndex(key);
if(arr[index] == null) {
arr[index] = new MyLinkedList();
}
arr[index].add(key, value);
}
/**
* 刪除資料
* @param key
* @return
*/
public boolean delete(int key) {
int index = getHashIndex(key);
if(arr[index] != null) {
return arr[index].delete(key);
}
return false;
}
/**
* 根據key獲取value
* @param key
* @return
*/
public String get(int key) {
int index = getHashIndex(key);
if(arr[index] != null) {
return arr[index].get(key);
}
return null;
}
/**
* 獲取陣列下標
* @param key
* @return
*/
private int getHashIndex(Integer key) {
return key.hashCode() % maxSize;
}
/**
* 遍歷陣列中所有連結串列的資料
* @return
*/
public String list() {
String str = "[ ";
for (int i = 0; i < maxSize; i++) {
if(arr[i] != null) {
str += arr[i].toString();
}
}
str = str.substring(0, str.length()-1);
str += " ]";
return str;
}
@Override
public String toString() {
return list();
}
}
```
測試類
```
public class Test {
public static void main(String[] args) {
MyHashMap map = new MyHashMap(20);
map.put(5, "aaa");
map.put(8, "bbb");
map.put(3, "ccc");
map.put(8, "bbb");
map.put(2, "ddd");
map.put(9, "eee");
System.out.println(map);
System.out.println(map.get(3));
System.out.println(map.delete(2));
System.out.println(map);
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2658544/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java學習路線分享maven是什麼程式設計師JavaMaven
- 好程式設計師大資料學習路線分享MAPREDUCE程式設計師大資料
- 好程式設計師大資料學習路線分享SparkSQl程式設計師大資料SparkSQL
- 好程式設計師大資料學習路線分享Hbase指令學習程式設計師大資料
- 好程式設計師大資料學習路線分享大資料之字串程式設計師大資料字串
- 好程式設計師大資料學習路線Hadoop學習乾貨分享程式設計師大資料Hadoop
- 好程式設計師大資料學習路線分享HDFS學習總結程式設計師大資料
- 好程式設計師大資料學習路線分享hdfs學習乾貨程式設計師大資料
- 好程式設計師大資料學習路線分享Actor學習筆記程式設計師大資料筆記
- 好程式設計師大資料學習路線分享Map學習筆記程式設計師大資料筆記
- 好程式設計師大資料學習路線分享HDFS讀流程程式設計師大資料
- 好程式設計師大資料學習路線分享AWK詳解程式設計師大資料
- 好程式設計師大資料學習路線分享UDF函式程式設計師大資料函式
- 好程式設計師大資料學習路線分享spark之Scala程式設計師大資料Spark
- 好程式設計師大資料學習路線分享Lambda表示式程式設計師大資料
- 好程式設計師web前端學習路線分享瞭解AJAX是什麼程式設計師Web前端
- 好程式設計師大資料學習路線分享大資料之執行緒程式設計師大資料執行緒
- 好程式設計師大資料學習路線分享高階函式程式設計師大資料函式
- 好程式設計師大資料學習路線分享Scala系列之物件程式設計師大資料物件
- 好程式設計師大資料學習路線分享Hadoop機架感知程式設計師大資料Hadoop
- 好程式設計師大資料學習路線分享TCP和UDP學習筆記程式設計師大資料TCPUDP筆記
- 好程式設計師大資料學習路線分享大資料之基礎語法程式設計師大資料
- 好程式設計師大資料學習路線分享MapReduce全過程解析程式設計師大資料
- 好程式設計師大資料學習路線分享hive的執行方式程式設計師大資料Hive
- 好程式設計師大資料學習路線分享Scala系列之抽象類程式設計師大資料抽象
- 好程式設計師大資料學習路線分享Scala系列之陣列程式設計師大資料陣列
- 好程式設計師大資料學習路線分享Scala分支和迴圈程式設計師大資料
- 好程式設計師大資料學習路線分享MapReduce全流程總結程式設計師大資料
- 好程式設計師大資料學習路線分享Scala系列之泛型程式設計師大資料泛型
- 好程式設計師大資料學習路線之大資料自學路線二程式設計師大資料
- 好程式設計師大資料學習路線之大資料自學路線一程式設計師大資料
- 好程式設計師大資料學習路線之hive表的查詢程式設計師大資料Hive
- 好程式設計師大資料學習路線分享執行緒學習筆記二程式設計師大資料執行緒筆記
- 好程式設計師大資料學習路線分享多執行緒學習筆記程式設計師大資料執行緒筆記
- 好程式設計師大資料學習路線Hbase總結程式設計師大資料
- 好程式設計師大資料學習路線之mapreduce概述程式設計師大資料
- 好程式設計師大資料學習路線分享彈性分散式資料集RDD程式設計師大資料分散式
- 好程式設計師大資料學習路線分享函式+map對映+元祖程式設計師大資料函式