Java Hashtable
Hashtable 类实现了一个哈希表,它将键映射到值。任何非空对象都可以被用作键或值。为了成功地从哈希表中存储和检索对象,用作键的对象必须实现hashCode方法和equals方法。
Hashtable的特点
- 它类似于HashMap,但是是同步的。
- Hashtable在哈希表中存储键/值对。
- 在Hashtable中,我们指定一个作为键的对象,以及我们想与该键关联的值。然后对键进行散列,得到的散列码被用作索引,该值被存储在表中。
- Hashtable类的初始默认容量是11,而loadFactor是0.75。
- HashMap不提供任何枚举,而Hashtable则不提供失效的枚举。
声明
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
类型参数
- K – 这个地图所维护的键的类型
- V– 映射的值的类型
Hashtable的层次结构

Hashtable实现了 Serializable 、 Cloneable 、Map<K,V>接口并扩展了Dictionary<K,V>。直接的子类是 Properties , UIDefaults .
构造函数
为了创建一个Hashtable,我们需要从 java.util.Hashtable 导入它 。 我们可以通过各种方式来创建一个Hashtable。
1.Hashtable(): 这将创建一个空的Hashtable,默认负载因子为0.75,初始容量为11。
Hashtable<K, V> ht = new Hashtable<K, V>()
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>();
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>();
// Inserting the Elements
// using put() method
ht1.put(1, "one");
ht1.put(2, "two");
ht1.put(3, "three");
ht2.put(4, "four");
ht2.put(5, "five");
ht2.put(6, "six");
// Print mappings to the console
System.out.println("Mappings of ht1 : " + ht1);
System.out.println("Mappings of ht2 : " + ht2);
}
}
输出
Mappings of ht1 : {3=three, 2=two, 1=one}
Mappings of ht2 : {6=six, 5=five, 4=four}
2.Hashtable(int initialCapacity): 这将创建一个哈希表,其初始大小由initialCapacity指定,默认的负载因子为0.75。
Hashtable<K, V> ht = new Hashtable<K, V>(int initialCapacity)
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>(4);
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(2);
// Inserting the Elements
// using put() method
ht1.put(1, "one");
ht1.put(2, "two");
ht1.put(3, "three");
ht2.put(4, "four");
ht2.put(5, "five");
ht2.put(6, "six");
// Print mappings to the console
System.out.println("Mappings of ht1 : " + ht1);
System.out.println("Mappings of ht2 : " + ht2);
}
}
输出
Mappings of ht1 : {3=three, 2=two, 1=one}
Mappings of ht2 : {4=four, 6=six, 5=five}
3.Hashtable(int size, float fillRatio): 这个版本创建了一个哈希表,其初始大小由size指定,填充率由fillRatio指定。基本上,它决定了一个哈希表在向上调整大小之前可以有多满,其值在0.0到1.0之间。
Hashtable<K, V> ht = new Hashtable<K, V>(int size, float fillRatio)
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1
= new Hashtable<>(4, 0.75f);
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(3, 0.5f);
// Inserting the Elements
// using put() method
ht1.put(1, "one");
ht1.put(2, "two");
ht1.put(3, "three");
ht2.put(4, "four");
ht2.put(5, "five");
ht2.put(6, "six");
// Print mappings to the console
System.out.println("Mappings of ht1 : " + ht1);
System.out.println("Mappings of ht2 : " + ht2);
}
}
输出
Mappings of ht1 : {3=three, 2=two, 1=one}
Mappings of ht2 : {6=six, 5=five, 4=four}
**4.Hashtable(Map <?extends K,?extends V> m): **这将创建一个哈希表,用m中的元素进行初始化。
Hashtable<K, V> ht = new Hashtable<K, V>(Map m)
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Map<Integer, String> hm = new HashMap<>();
// Inserting the Elements
// using put() method
hm.put(1, "one");
hm.put(2, "two");
hm.put(3, "three");
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>(hm);
// Print mappings to the console
System.out.println("Mappings of ht2 : " + ht2);
}
}
输出
Mappings of ht2 : {3=three, 2=two, 1=one}
例子
// Java program to illustrate
// Java.util.Hashtable
import java.util.*;
public class GFG {
public static void main(String[] args)
{
// Create an empty Hashtable
Hashtable<String, Integer> ht = new Hashtable<>();
// Add elements to the hashtable
ht.put("vishal", 10);
ht.put("sachin", 30);
ht.put("vaibhav", 20);
// Print size and content
System.out.println("Size of map is:- " + ht.size());
System.out.println(ht);
// Check if a key is present and if
// present, print value
if (ht.containsKey("vishal")) {
Integer a = ht.get("vishal");
System.out.println("value for key"
+ " \"vishal\" is:- " + a);
}
}
}
输出
Size of map is:- 3
{vaibhav=20, vishal=10, sachin=30}
value for key "vishal" is:- 10
对Hashtable进行各种操作
1.添加元素: 为了向hashtable添加一个元素,我们可以使用put()方法。然而,插入的顺序并没有保留在hashtable中。在内部,对于每一个元素,都会产生一个单独的哈希值,并且基于这个哈希值对元素进行索引,以使其更有效率。
// Java program to demonstrate
// adding elements to Hashtable
import java.io.*;
import java.util.*;
class AddElementsToHashtable {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Hashtable<Integer, String> ht1 = new Hashtable<>();
// Initialization of a Hashtable
// using Generics
Hashtable<Integer, String> ht2
= new Hashtable<Integer, String>();
// Inserting the Elements
// using put() method
ht1.put(1, "Geeks");
ht1.put(2, "For");
ht1.put(3, "Geeks");
ht2.put(1, "Geeks");
ht2.put(2, "For");
ht2.put(3, "Geeks");
// Print mappings to the console
System.out.println("Mappings of ht1 : " + ht1);
System.out.println("Mappings of ht2 : " + ht2);
}
}
输出
Mappings of ht1 : {3=Geeks, 2=For, 1=Geeks}
Mappings of ht2 : {3=Geeks, 2=For, 1=Geeks}
2.改变元素: 在添加元素后,如果我们想改变元素,可以通过put()方法再次添加元素来完成。由于hashtable中的元素是用键来索引的,所以键的值可以通过简单地插入我们想改变的键的更新值来改变。
// Java program to demonstrate
// updating Hashtable
import java.io.*;
import java.util.*;
class UpdatesOnHashtable {
public static void main(String args[])
{
// Initialization of a Hashtable
Hashtable<Integer, String> ht
= new Hashtable<Integer, String>();
// Inserting the Elements
// using put method
ht.put(1, "Geeks");
ht.put(2, "Geeks");
ht.put(3, "Geeks");
// print initial map to the console
System.out.println("Initial Map " + ht);
// Update the value at key 2
ht.put(2, "For");
// print the updated map
System.out.println("Updated Map " + ht);
}
}
输出
Initial Map {3=Geeks, 2=Geeks, 1=Geeks}
Updated Map {3=Geeks, 2=For, 1=Geeks}
3.删除元素: 为了从地图中删除一个元素,我们可以使用remove()方法。该方法接收键值,如果该键存在于地图中,则从该地图中删除该键的映射。
// Java program to demonstrate
// the removing mappings from Hashtable
import java.io.*;
import java.util.*;
class RemovingMappingsFromHashtable {
public static void main(String args[])
{
// Initialization of a Hashtable
Map<Integer, String> ht
= new Hashtable<Integer, String>();
// Inserting the Elements
// using put method
ht.put(1, "Geeks");
ht.put(2, "For");
ht.put(3, "Geeks");
ht.put(4, "For");
// Initial HashMap
System.out.println("Initial map : " + ht);
// Remove the map entry with key 4
ht.remove(4);
// Final Hashtable
System.out.println("Updated map : " + ht);
}
}
输出
Initial map : {4=For, 3=Geeks, 2=For, 1=Geeks}
Updated map : {3=Geeks, 2=For, 1=Geeks}
4.遍历哈希表: 为了遍历该表,我们可以使用一个高级for循环。下面是遍历一个哈希表的例子。
// Java program to illustrate
// traversal of Hashtable
import java.util.Hashtable;
import java.util.Map;
public class IteratingHashtable {
public static void main(String[] args)
{
// Create an instance of Hashtable
Hashtable<String, Integer> ht = new Hashtable<>();
// Adding elements using put method
ht.put("vishal", 10);
ht.put("sachin", 30);
ht.put("vaibhav", 20);
// Iterating using enhanced for loop
for (Map.Entry<String, Integer> e : ht.entrySet())
System.out.println(e.getKey() + " "
+ e.getValue());
}
}
输出
vaibhav 20
vishal 10
sachin 30
哈希图表的内部工作
Hashtable数据结构是一个存储键/值对的桶的数组。它利用 hashCode()方法 来确定键/值对应该映射到哪个桶。
散列函数有助于确定一个给定的键在桶列表中的位置。一般来说,hashcode是一个非负的整数,对于相等的对象来说是相等的,对于不相等的对象来说可能是相等的,也可能不是。为了确定两个对象是否相等,hashtable使用了equals()方法。
两个不相等的对象有可能有相同的哈希码。这被称为 碰撞 为了解决碰撞问题,hashtable使用一个列表数组。映射到单个桶(数组索引)的对被存储在一个列表中,列表引用被存储在数组索引中。

Hashtable的方法
- K – 地图中键的类型。
- V – 在地图中映射的值的类型。
| 方法 | 描述 |
|---|---|
| clear() | 清除这个hashtable,使其不包含任何键。 |
| clone() | 创建这个hashtable的一个浅层拷贝。 |
| compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 试图为指定的键和其当前的映射值计算一个映射(如果没有当前的映射,则为空)。 |
| computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) | 如果指定的键还没有与一个值相关联(或者被映射为空),则尝试使用给定的映射函数计算其值,并将其输入此映射中,除非为空。 |
| computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 如果指定的键的值是存在的,并且不是空的,则尝试给定键和其当前的映射值来计算一个新的映射。 |
| contains(Object value) | 测试某个键是否映射到这个hashtable中的指定值。 |
| containsKey(Object key) | 测试指定的对象是否是这个hashtable中的一个键。 |
| containsValue(Object value) | 如果这个hashtable将一个或多个键映射到这个值,返回true。 |
| elements() | 返回这个hashtable中的值的枚举。 |
| entrySet() | 返回这个地图中包含的映射的Set视图。 |
| equals(Object o) | 根据Map接口中的定义,将指定的Object与此Map进行比较,看是否相等。 |
| get(Object key) | 返回指定的键被映射到的值,如果此地图不包含键的映射,则返回空值。 |
| hashCode() | 按照地图接口的定义,返回该地图的哈希代码值。 |
| isEmpty() | 测试这个hashtable是否没有将键映射到值。 |
| keys() | 返回这个hashtable中的键的枚举值。 |
| keySet() | 返回这个地图中包含的键的Set视图。 |
| merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) | 如果指定的键还没有与一个值相关联或者与空值相关联,那么将其与给定的非空值相关联。 |
| put(K key, V value) | 将指定的键映射到这个hashtable中的指定值。 |
| putAll(Map<? extends K,? extends V> t) | 将指定地图中的所有映射复制到这个hashtable中。 |
| rehash() | 增加这个hashtable的容量并在内部进行重组,以便更有效地容纳和访问其条目。 |
| remove(Object key) | 从这个hashtable中删除键(和它的相应值)。 |
| size() | 返回这个hashtable中的键的数量。 |
| toString() | 返回这个Hashtable对象的字符串表示,其形式是一组条目,用大括号括起来,用ASCII字符”,”(逗号和空格)分开。 |
| value() | 返回该地图中包含的值的集合视图。 |
java.util.Map接口中声明的方法
| 方法 | 描述 |
|---|---|
| forEach(BiConsumer<? super K,? super V> action) | 对该地图中的每个条目执行给定的操作,直到所有条目都被处理完,或者该操作抛出一个异常。 |
| getOrDefault(Object key, V defaultValue) | 返回指定的键被映射到的值,如果这个地图不包含键的映射,则返回defaultValue。 |
| putIfAbsent(K key, V value) | 如果指定的键还没有与一个值相关联(或者被映射为null),则将其与给定的值相关联并返回null,否则返回当前值。 |
| remove(Object key, Object value) | 只有当指定的键当前被映射到指定的值时,才会删除该键的条目。 |
| replace(K key, V value) | 只有当指定的键当前被映射到某个值时,才会替换该键的条目。 |
| replace(K key, V oldValue, V newValue) | 只在当前映射到指定值的情况下替换指定键的条目。 |
| replaceAll(BiFunction<? super K,? super V,? extends V> function) | 用对该条目调用给定函数的结果替换每个条目的值,直到所有条目都被处理或该函数抛出一个异常。 |
极客教程