CodeGym /Java Blog /Toto sisi /Java哈希表
John Squirrels
等級 41
San Francisco

Java哈希表

在 Toto sisi 群組發布
Java Hashtable類是 Java Collection Framework 最古老的成員之一。它是數學哈希表數據結構的一種實現。在 Java 中,哈希表內部包含存儲鍵/值對的存儲桶。Hashtable與HashMap非常相似。它們之間最顯著的區別:Hashtable是同步的而HashMap不是。

哈希表作為一種數據結構

哈希表是一種數據結構,其中數據以數組格式存儲。每個數據值都有一個唯一的鍵值。如果密鑰已知,則訪問所需數據的速度非常快。因此,插入和搜索操作的速度與數據大小無關。哈希表由一個用於保存數據的數組和用於生成元素所在位置的索引的哈希組成。什麼是散列?是將Object映射成一組字符(代碼)的規則。通常那種函數將一大段數據轉換成一個小的整數值。哈希函數可能不同,但它們都提交某些屬性:
  • 特定對象具有特定的哈希碼。
  • 兩個相等的對象具有相同的哈希碼。反之則不然。
  • 如果兩個哈希碼不同,則對象肯定不相等。
  • 不同的對象可能具有相同的哈希碼。這種非常罕見的事件稱為碰撞。良好的散列函數最大限度地減少了衝突的可能性。
將哈希函數應用於對象的結果調用hashCode

Java 中的哈希表

Hashtable類是哈希表數據結構的實現。這個集合創建的時間早於 Java Collection Framework,但後來被包含在其中。與所有“早期”集合(來自 Java 1.0)一樣,哈希表是同步的(幾乎所有方法都標記為同步)。由於這個因素,哈希表具有顯著的性能問題。因此,從 Java 1.2 開始,在大多數情況下建議使用Map接口的其他實現,因為它們缺乏同步。通常HashMap是最合適的替代品。所以類Hashtable<K,V>由鍵和值組成。它根據散列原理存儲密鑰。鍵值對存儲在“桶”中。這些桶一起構成了一個“表”,一種內部數組。哈希表使用鍵的哈希碼來確定鍵/值對應映射到的存儲桶。哈希函數允許從 Key 的哈希碼中獲取桶位置。此函數返回對象的整數。正如我們上面所說,兩個相等的對象具有相同的哈希碼,而兩個不相等的對象可能並不總是具有不同的哈希碼。放入哈希表中的不同對象可能具有相同的哈希碼。為了解決這個問題(衝突),哈希表中使用了列表數組。映射到單個桶的對存儲在列表中,該列表引用存儲在數組索引中。

哈希表 Java 構造函數

  • Hashtable(),默認構造函數。它創建一個空的哈希表。(默認初始容量 = 11,負載係數 =0.75)。
  • Hashtable(int size)構造指定大小的哈希表。
  • Hashtable(int size, float fillRatio)創建指定大小和填充率的哈希表。
  • Hashtable(Map m)創建一個哈希表,其映射與給定的 Map 相同。

哈希表聲明

Hashtable Java 類實現了Map CloneableSerializable接口。它擴展了Dictionary類。

Hashtable.java
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable
K是地圖維護的鍵的類型。 V是映射值的類型。例子:

Hashtable<Student, Integer> myHTable = new Hashtable<>();

如何導入哈希表java

Java Hashtable 位於java.util包中。所以使用import java.util.Hashtable; 在你的代碼中。通常您會從您的 IDE 中得到關於此的提示。

哈希表主要操作

Hashtable 的主要操作是獲取、插入集合和從集合中移除。這三個操作是:
  • Object get(Object key)返回具有指定鍵的對象的值。如果找不到這樣的鍵,則返回 null。
  • Object put(Object key, Object value)將指定的鍵映射到指定的值。鍵和值都不能為空。
  • Object remove(Object key)從哈希表中刪除條目(鍵和對應的值)。
其他重要操作:
  • int size()返回哈希表中條目的數量。
  • boolean contains(Object value)檢查指定值是否在哈希表中。如果是,則方法返回 true,否則返回 false。
  • boolean containsValue(Object value)檢查指定值是否在哈希表中。如果是,則方法返回 true,否則返回 false。
  • void clear()從哈希表中刪除所有條目。
  • boolean containsKey(Object key)如果哈希表中存在指定的鍵,則返回 true,否則返回 false。
  • boolean isEmpty()如果哈希表為空則返回 true,如果它包含至少一個鍵則返回 false。
  • void rehash()增加哈希表的大小並重新哈希其所有鍵。

哈希表實現,Java代碼:

讓我們創建一個學生類:

import java.util.Date;
public class Student {
   String surname;
   String name;
   String secondName;
   Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases

   public Student(String surname, String name, String secondName, Date birthday ){
       this.surname = surname;
       this.name = name;
       this.secondName = secondName;
       this.birthday = birthday == null ? 0 : birthday.getTime();
   }

   @Override
   public int hashCode(){
       //TODO: check for nulls
       return (surname + name + secondName + birthday).hashCode();
   }
   @Override
   public boolean equals(Object other_) {
       Student other = (Student)other_;
       return (surname == null || surname.equals(other.surname) )
               && (name == null || name.equals(other.name))
               && (secondName == null || secondName.equals(other.secondName))
               && (birthday == null || birthday.equals(other.birthday));
   }
}
這是 Java Hashtable示例。讓我們將Student類的兩個對象放入哈希表中,然後刪除一些並檢查一些參數。

public class HashTableExample {
   public static void main(String[] args) {
 
       Hashtable<Student, Integer> myHTable = new Hashtable<>();
       Student sarah1 = new Student("Sarah","Connor", "Jane", null);
       Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
       myHTable.put(john,1);
       myHTable.put(sarah1,0);
       System.out.println(myHTable.get(john));
       System.out.println(myHTable.isEmpty());
       System.out.println(myHTable.size());
       System.out.println(myHTable.contains(1));
       myHTable.remove(john);
       System.out.println(myHTable.contains(0));
       System.out.println(myHTable.contains(1));
       System.out.println(myHTable.containsKey(sarah1));
   }
}
程序運行結果為:

1
false
2
true
true
false
true

HashMap 與哈希表

  • Hashtable 類似於 Java 中的 HashMap。最顯著的區別是 Hashtable 是同步的,而 HashMap 不是。因此,Hashtable 比 HashMap 慢,因為同步。
  • 除了同步問題,Hashtable 不允許使用 null 作為值或鍵。HashMap 允許一個空鍵和多個空值。
  • Hashtable繼承Dictionary類,HashMap繼承AbstractMap類。
  • HashMap 由 Iterator 遍歷。Hashtable不僅可以被Iterator遍歷,也可以被Enumerator遍歷。

Java 哈希表示例(Hashtable 與 HashMap 空鍵)

這是一個片段代碼,用於演示在HashMapHashtable中用作鍵和值的 null

// Null key Java hashtable example and hashmap example  

try{
      System.out.println("Hashtable");
      Hashtable hashTable = new Hashtable();
      hashTable.put(null, new Object());
    }catch(Exception ex){
      ex.printStackTrace();
    }
    System.out.println("HashMap");
    HashMap hashMap = new HashMap();
    hashMap.put(null, new Object());
    System.out.println("as you see no exceptions with null key in HashMap");
  }
運行包含此片段的程序的結果:

java.lang.NullPointerException
	at java.base/java.util.Hashtable.put(Hashtable.java:480)
	at Character.main(Character.java:58)
HashMap
as you see no exceptions with null key in HashMap

結論

在實際項目中你不會經常用到Hashtable,但是在老項目中很容易遇到這種數據結構。無論如何,重要的是要了解 Java 有哪些數據結構以及它們是如何工作的,至少對於你的面試來說是這樣。通常使用 HashMap 對象而不是 Hashtable 因為它們的相似性。HashMap 更有效(它不是同步的)並且可以將 null 作為鍵。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION