Hashtable全面使用-Java快速入门教程
Java中的Hashtable类是抽象字典类(Dictionary )的具体实现。
它是一种类似于 HashMap的数据结构,可以以键值对(条目)的形式存储元素(对象)的集合。
键对象必须实现 hashCode() 和 equals() 方法来存储和检索 Hashtable 中的值。
换句话说,Hashtable 只能存储重写了 Object 类定义的 hashCode() 和 equals() 方法的键对象。
Hashtable和 HashMap 之间的主要区别在于它们使用线程访问的方式。
- Hashtable是一个同步类,这意味着它是线程安全的。多个线程不能同时(同时)访问哈希表类的同一实例。
- HashMap 是一个未同步,这意味着它不是线程安全的。多个线程可以同时访问 HashMap 类的同一实例,另仅当一个线程使用对象时才安全。
Java Hashtable 在 JDK 1.0 版本中添加,并存在于 java.util.Hashtable 包中。在 JDK 1.2 版本之前,Hashtable 用于将键与值映射。
后来,Java 1.2版本修改了Hashtable,使其实现了Map接口。因此,Hashtable已经与Java集合框架集成。
但它与Java集合框架不太一致,它现在被视为“遗留类”。
Java 哈希表的层次结构
哈希表类扩展了字典类并实现了映射、可克隆和可序列化接口。Java中Hashtable的层次结构图如下图所示。
Hashtable 类声明
Hashtable 在 JDK 1.5 开始引入泛型类,可以声明如下:
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
在这里,哈希表接受两个参数 K 和 V,其中 K 表示键的类型,V 定义值的类型。
哈希表的特点
Java 中 Hashtable 有几个功能必须牢记才能使用它。
1. Java 哈希表的底层数据结构只是一个哈希表(hash table)。
2. 不保证插入与检索时顺序一致。这意味着它不会保持插入顺序。
3. 不允许重复键,但值可以重复。
4. 键和值都允许异构对象。
5. 键和值都不允许为 Null。如果我们尝试存储空键或值,我们将得到一个名为 NullPointerException 的 RuntimeException。
6. Java 哈希表实现了可序列化和可克隆的接口,但不是随机访问。
7. 哈希表中存在的每个方法都是同步的。因此,哈希表对象是线程安全的。
8. 如果我们的频繁操作是检索(搜索)操作,则哈希表是最佳选择。
9. 由于哈希表是同步的,因此与 Java 中的哈希映射相比,其操作速度较慢。
Java 中哈希表类的构造函数
哈希表类定义以下构造函数,如下所示:
1. Hashtable():这种形式的构造函数构造一个新的空哈希表对象,默认初始容量为 11,负载因子为 0.75。
要将字符串存储为键,将整数对象存储为其值,我们可以创建一个 Hashtable 对象为:
Hashtable<String,Integer> ht = new Hashtable<>();
此哈希表对象的默认初始容量将取为 11,负载因子为 0.75。
2. Hashtable(int initialCapacity):此构造函数构造一个新的空哈希表,其指定的初始容量和默认负载因子为 0.75。如果初始容量小于零,它将引发一个名为 IllegalArgumentException 的异常。
3. Hashtable(int initialCapacity, float loadFactor):此构造函数构造一个新的空哈希表,具有指定的初始容量和指定的负载因子。
4. Hashtable(Map m):这种形式的构造函数构造一个新的哈希表,具有与给定 Map 相同的映射。如果指定的映射为 null,它将抛出 NullPointerException。
Java 中的哈希表方法
Java Hashtable 类定义了以下遗留方法:
1.void clear(): 它用于从哈希表中清除所有键值对。
2. Object clone():此方法用于创建此哈希表的浅拷贝。
3. V put(K key, V value): 此方法用于将键值对映射到哈希表中。
4. void putAll(Map t):此方法将所有键值对(映射)从指定映射复制到哈希表中。
5. boolean isEmpty():如果哈希表中没有条目,则返回 true。
6. int size():此方法用于检索哈希表中键值对的数量。
7. V remove(Object key):此方法用于从哈希表中删除键(及其关联值)。
8. boolean remove(Object key, Object value):仅当指定键当前映射到指定值时,此方法才会删除指定键的条目。
9. V replace(K key, V value): 此方法仅用于替换指定键的条目,前提是该条目当前映射到某个值。
10. boolean replace(K key, V oldValue, V newValue): 此方法仅在当前映射到指定值时才替换指定键的键值对。
11. boolean contains(Object value): 此方法检查哈希表,如果哈希表包含指定值,则返回 true。
12. boolean containsKey(Object key): 此方法搜索哈希表,如果哈希表中指定的键对象返回 true。
13. boolean containsValue(Object value):此方法搜索哈希表,如果此哈希表将一个或多个键映射到此值,则返回 true。
14. Enumeration<V> elements():此方法返回此哈希表中值的枚举。
15. Enumeration<K> keys(): 此方法返回此哈希表中键的枚举。
16. Set<Map.Entry<K,V>> entrySet(): 此方法返回此映射中包含的映射的集合或集合视图。
17. Set<K> keySet():它返回此映射中包含的键的集合视图。
18. Collection<V> values(): 它返回此映射中包含的值的集合视图。
19. V get(Object key):它返回与其指定键关联的值。如果键没有与之关联的值,则返回 null。
20. boolean equals(Object o):它用于根据Map接口中的定义比较指定的对象是否相等。
21.int hashCode(): 此方法根据 Map 接口中的定义返回哈希代码的值。
22. String toString(): 此方法用于将 Hashtable 对象转换为一组条目形式的字符串,用大括号括起来,用 ASCII 字符 “”、“”(逗号和空格)分隔并返回它。
Java Hashtable 示例程序
让我们以各种示例程序为例,这些程序基于java中的哈希表方法执行操作。
1.让我们创建一个程序,我们将在其中执行各种操作,例如添加,删除,检查哈希表是否为空,然后再添加元素,最后检查其大小。
在此示例中,我们将创建一个默认初始容量为 11、负载因子为 0.75 的构造函数。查看源代码以更好地理解。
程序源代码 1:
import java.util.Hashtable; public class HashtableEx { public static void main(String[] args) { // Create a Hashtable object. Hashtable<Integer, String> ht = new Hashtable<Integer, String>(); // Checking hashtable is empty or not. boolean isEmpty = ht.isEmpty(); System.out.println("Is hash table empty: " +isEmpty); // Adding entries using put() method in hash table. ht.put(1, "One"); // ht.size() is 1. ht.put(2, "Two"); // ht.size() is 2. ht.put(3, "Three"); // ht.size() is 3. ht.put(4, "Four"); // ht.size() is 4. ht.put(5, "Five"); // ht.size() is 5. ht.put(6, "Six"); // ht.size() is 6. System.out.println("Displaying entries in hash table: " +ht); int size = ht.size(); System.out.println("Size of hash table: " +size); // Removing last entry. String removeE = ht.remove(6); System.out.println("Removed entry: " +removeE); System.out.println("Updated entries in hash table: " +ht); // Getting the value of 4. String getValue = ht.get(4); System.out.println("Getting the value of 4: " +getValue); System.out.println("Getting the value of 2: " +ht.get(2)); } }
Output: Is hash table empty: true Displaying entries in hash table: {6=Six, 5=Five, 4=Four, 3=Three, 2=Two, 1=One} Size of hash table: 6 Removed entry: Six Updated entries in hash table: {5=Five, 4=Four, 3=Three, 2=Two, 1=One} Getting the value of 4: Four Getting the value of 2: Two
正如您在程序输出中观察到的那样,插入顺序不会保留在哈希表中。在内部,对于每个条目,都会生成一个单独的键哈希代码,并根据键的哈希代码对条目进行索引,以使其更有效率。
2. 让我们创建另一个程序,我们将基于replace(), containsKey(), and containsValue()等方法执行各种操作。
程序源代码 2:
import java.util.Hashtable; public class HashtableEx2 { public static void main(String[] args) { // Create a Hashtable object. Hashtable<String, Integer> ht = new Hashtable<>(); ht.put("John", 20); ht.put("Shubh", 30); ht.put("Peter", 25); ht.put("Deep", 15); ht.put("Jonshan", 40); System.out.println("Original entries of hash table: " +ht); // Replacing an entry for specified key from hash table. Integer replace = ht.replace("Peter", 60); System.out.println("Replacing entry for specified key: " +replace); System.out.println("Updated entries in hash table: " +ht); // Checking specified key present in hash table. boolean containsKey = ht.containsKey("Shubh"); System.out.println("Is key Shubh in hash table: " +containsKey); // Checking specified value present in hash table. boolean containsValue = ht.containsValue(40); System.out.println("Is value 40 in hash table: " +containsValue); } }
Output: Original entries of hash table: {John=20, Jonshan=40, Shubh=30, Deep=15, Peter=25} Replacing entry for specified key: 25 Updated entries in hash table: {John=20, Jonshan=40, Shubh=30, Deep=15, Peter=60} Is key Shubh in hash table: true Is value 40 in hash table: true
3. 让我们举一个示例程序,我们将使用 iterator()、keySet()、values() 和 entrySet() 迭代哈希表的键、值和条目。
程序源代码 3:
import java.util.Hashtable; import java.util.Iterator; import java.util.Map.Entry; public class HashtableEx { public static void main(String[] args) { Hashtable<String, Integer> ht = new Hashtable<>(); ht.put("John", 20); ht.put("Shubh", 30); ht.put("Peter", 25); ht.put("Deep", 15); ht.put("Jonshan", 40); System.out.println("Original entries of hash table: " +ht); // Iterating elements of hash table using iterator() method. System.out.println("Iterating keys of hash table:"); Iterator<String> itr = ht.keySet().iterator(); while(itr.hasNext()) { System.out.println(itr.next()); } System.out.println("\n"); System.out.println("Iterating values of hash table:"); Iterator<Integer> itrValue = ht.values().iterator(); while(itrValue.hasNext()) { System.out.println(itrValue.next()); } System.out.println("\n"); System.out.println("Iterating entries of hash table:"); Iterator<Entry<String, Integer>> itrEntry = ht.entrySet().iterator(); while(itrEntry.hasNext()) { System.out.println(itrEntry.next()); } } }
Output: Original entries of hash table: {John=20, Jonshan=40, Shubh=30, Deep=15, Peter=25} Iterating keys of hash table: John Jonshan Shubh Deep Peter Iterating values of hash table: 20 40 30 15 25 Iterating entries of hash table John=20 Jonshan=40 Shubh=30 Deep=15 Peter=25