CodeGym /Java 博客 /随机的 /Java哈希表
John Squirrels
第 41 级
San Francisco

Java哈希表

已在 随机的 群组中发布
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