哈希表中的每個位置稱爲桶(bucket),當發生哈希衝突時就以鏈表形式存放多個元素。
鏈地址法處理Hash衝突,看看下面代碼,模擬了JDK中的HashSet:
結果:
index:4 value:Tom
index:1 value:Mike
index:1 value:Mike
index:5 value:Jack
index:5 value:Mary
index:0 value:Linda
index:0 value:Rose
index:0 value:Jone
size=6
Linda
Rose
Jone
Mike
Tom
Jack
true
true
false
鏈地址法處理Hash衝突,看看下面代碼,模擬了JDK中的HashSet:
- class Node{ //節點數據結構
- private Object value; //節點的值
- private Node next; //鏈表中指向下一結點的引用
- /*提供了常見的操作*/
- public Node(Object value){ this .value = value;};
- public Object getValue() { return value;}
- public Node getNext() { return next;}
- public void setNext(Node next){ this .next=next;}
- }
- public class MyHashSet { //Hash數據結構
- private Node[] array; //存儲數據鏈表的數組
- private int size = 0 ; //表示集合中存放的對象的數目
- public MyHashSet( int length){
- array = new Node[length]; //創建數組
- }
- public int size(){
- return size;
- }
- private static int hash (Object o){ //根據對象的哈希碼得到一個優化的哈希碼,
- //算法參照java.util.HashMap的hash()方法
- int h = o.hashCode();
- h += ~(h<<9 );
- h ^= (h>>>14 );
- h += (h<<4 );
- h ^= (h>>>10 );
- return h;
- }
- private int indexFor( int hashCode){ //根據Hash碼得到其索引位置
- //算法參照java.util.HashMap的indexFor()方法
- return hashCode & (array.length- 1 );
- }
- public void add(Object value) { //把對象加入集合,不允許加入重複的元素
- int index = indexFor(hash(value)); //先根據value得到index
- System.out.println("index:" + index + " value:" + value);
- Node newNode = new Node(value); //由value創建一個新節點newNode
- Node node = array[index];//由index得到一個節點node
- if (node == null ) { //若這個由index得到的節點是空,則將新節點放入其中
- array[index]=newNode;
- size++;
- } else {
- //若不爲空則遍歷這個點上的鏈表(下一個節點要等於空或者該節點不等於新節點的值--不允許重複)
- Node nextNode;
- while (!node.getValue().equals(value) && (nextNode = node.getNext())!= null ) {
- node = nextNode;
- }
- if (!node.getValue().equals(value)) {
- //若值不相等則加入新節點
- node.setNext(newNode);
- size++;
- }
- }
- }
- public boolean contains(Object value){
- int index = indexFor(hash(value));
- Node node = array[index];
- while (node!= null && !node.getValue().equals(value)) {
- node = node.getNext();
- }//橫向查找
- if (node!= null && node.getValue().equals(value)) {
- return true ;
- } else {
- return false ;
- }
- }
- public boolean remove(Object value) {
- int index = indexFor(hash(value));
- Node node = array[index];
- if (node!= null && node.getValue().equals(value)) { //若是第一個節點就是要remove的
- array[index]=node.getNext();
- size--;
- return true ;
- }
- Node lastNode = null ;
- while (node!= null && !node.getValue().equals(value)) { //若不是第一個節點就橫向查找
- lastNode = node;//記錄上一個節點
- node = node.getNext();
- }
- if (node!= null && node.getValue().equals(value)) {
- lastNode.setNext(node.getNext());
- size--;
- return true ;
- }else {
- return false ;
- }
- }
- public Object[] getAll() {
- Object [] values = new Object[size];
- int index = 0 ;
- for ( int i = 0 ; i < array.length; i++) {
- Node node = array[i];
- while (node!= null ) {
- values[index++]=node.getValue();
- node = node.getNext();
- }
- }
- return values;
- }
- public static void main(String[] args) {
- MyHashSet set = new MyHashSet( 6 );
- Object [] values = {"Tom" , "Mike" , "Mike" , "Jack" , "Mary" , "Linda" , "Rose" , "Jone" };
- for ( int i = 0 ; i < values.length; i++) {
- set.add(values[i]);
- }
- set.remove("Mary" );
- System.out.println("size=" +set.size());
- values = set.getAll();
- for ( int i = 0 ; i < values.length; i++) {
- System.out.println(values[i]);
- }
- System.out.println(set.contains("Jack" ));
- System.out.println(set.contains("Linda" ));
- System.out.println(set.contains("Jane" ));
- }
- }
結果:
index:4 value:Tom
index:1 value:Mike
index:1 value:Mike
index:5 value:Jack
index:5 value:Mary
index:0 value:Linda
index:0 value:Rose
index:0 value:Jone
size=6
Linda
Rose
Jone
Mike
Tom
Jack
true
true
false