Java中的Hashtable

Java中的Hashtable

Hashtable类实现了哈希表,可以将键映射到值。任何非空对象都可以用作键或值。要成功地从哈希表中存储和检索对象,作为键使用的对象必须实现hashCode方法和equals方法。

java.util.Hashtable类是Java中提供的一种键值数据结构,类似于Map接口。它是最初的Java集合框架的一部分,并在Java 1.0中引入。

然而,Hashtable类自引入集合框架以来已被认为过时,并且通常不建议使用。这是因为它是在引入集合框架之前设计的,没有实现Map接口,这使得它难以与框架的其他部分一起使用。此外,Hashtable类是同步的,与Map接口的其他实现相比,可能导致性能较慢。

一般建议使用Map接口或其实现之一(例如HashMap或ConcurrentHashMap)而不是Hashtable类。

以下是使用Hashtable类的示例:

import java.util.Enumeration;
import java.util.Hashtable;

public class Main {
    public static void main(String[] args) {
        Hashtable<String, Integer> hashtable = new Hashtable<>();

        //将元素添加到Hashtable中
        hashtable.put("A", 1);
        hashtable.put("B", 2);
        hashtable.put("C", 3);

        //从Hashtable中获取值
        int valueA = hashtable.get("A");
        System.out.println("A的值: " + valueA);

        //从Hashtable中删除元素
        hashtable.remove("B");

        //枚举Hashtable的元素
        Enumeration<String> keys = hashtable.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            System.out.println("键: " + key + ", 值: " + hashtable.get(key));
        }
    }
}

输出结果:

A的值: 1
键: A, 值: 1
键: C, 值: 3

总之,虽然Hashtable类仍然存在于Java中并且仍然可以使用,但一般建议使用Map接口或其实现。

Hashtable的特点:

  • 它类似于HashMap,但是是同步的。
  • Hashtable将键/值对存储在哈希表中。
  • 在Hashtable中,我们指定用作键的对象以及我们要将其关联的值。然后,将哈希了的键,并使用得到的哈希码作为存储值在表中的索引。
  • Hashtable类的初始默认容量为11,而loadFactor为0.75。
  • HashMap不提供任何枚举,而Hashtable提供不会立即失败的枚举。

声明:

public class Hashtable extends Dictionary implements Map, Cloneable, Serializable

类型参数:

  • K - 此映射所维护的键的类型。
  • V - 映射的值的类型。

Hashtable的继承关系

Java中的Hashtable

Hashtable实现了Serializable、Cloneable和Map<K,V>接口,并扩展了Dictionary<K,V>。直接子类是Properties和UIDefaults。

构造函数:

为了创建Hashtable,我们需要从 java.util.Hashtable 导入它。有许多种方法可以创建Hashtable。

1. 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程序演示
//向哈希表中添加元素
 
import java.io.*;
import java.util.*;
 
class AddElementsToHashtable {
    public static void main(String args[])
    {
        //无需再次指定
        //泛型类型
        Hashtable<Integer, String> ht1
            = new Hashtable<>(4, 0.75f);
 
        //使用泛型初始化哈希表
        Hashtable<Integer, String> ht2
            = new Hashtable<Integer, String>(3, 0.5f);
 
        //使用put()方法插入元素
        ht1.put(1, "one");
        ht1.put(2, "two");
        ht1.put(3, "three");
 
        ht2.put(4, "four");
        ht2.put(5, "five");
        ht2.put(6, "six");
 
        //打印哈希映射到控制台
        System.out.println("ht1的映射:" + ht1);
        System.out.println("ht2的映射:" + ht2);
    }
}

输出结果

ht1的映射:{3=three, 2=two, 1=one}
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程序演示
//向哈希表添加元素
 
import java.io.*;
import java.util.*;
 
class AddElementsToHashtable {
    public static void main(String args[])
    {
        //无需再次指定
        //泛型类型
        Map<Integer, String> hm = new HashMap<>();
 
        //使用put()方法插入元素
        hm.put(1, "one");
        hm.put(2, "two");
        hm.put(3, "three");
 
        //使用泛型初始化哈希表
        Hashtable<Integer, String> ht2
            = new Hashtable<Integer, String>(hm);
 
        //打印哈希映射到控制台
 
        System.out.println("ht2的映射:" + ht2);
    }
}

输出结果

ht2的映射:{3=three, 2=two, 1=one}

示例:

//Java程序演示
//Java.util.Hashtable
 
import java.util.*;
 
public class GFG {
    public static void main(String[] args)
    {
        //创建空Hashtable
        Hashtable<String, Integer> ht = new Hashtable<>();
 
        //向哈希表添加元素
        ht.put("vishal", 10);
        ht.put("sachin", 30);
        ht.put("vaibhav", 20);
 
        //打印哈希表大小和内容
        System.out.println("map的大小是:-" + ht.size());
        System.out.println(ht);
 
        //检查键是否存在以及是否存在,如果有,则打印它的值
        if (ht.containsKey("vishal")) {
            Integer a = ht.get("vishal");
            System.out.println("\"vishal\"键的值是: " + a);
        }
    }
}

输出结果

map的大小是:- 3
{vaibhav=20, vishal=10, sachin=30}
"vishal"键的值是: 10

在Hashtable上执行各种操作

1. 添加元素: 为了向哈希表中添加一个元素,我们可以使用put()方法。然而,哈希表中不会保留插入顺序。在内部,对于每个元素,生成一个单独的哈希,并根据此哈希对元素进行索引,使其更加有效。

// 演示向Hashtable添加元素的Java程序

import java.io.*;
import java.util.*;

class AddElementsToHashtable {
    public static void main(String args[])
    {
        // 不需要两次提及泛型
        Hashtable ht1 = new Hashtable<>();

        // 使用泛型初始化Hashtable
        Hashtable ht2 = new Hashtable();

        // 使用put()方法插入元素
        ht1.put(1, "Geeks");
        ht1.put(2, "For");
        ht1.put(3, "Geeks");

        ht2.put(1, "Geeks");
        ht2.put(2, "For");
        ht2.put(3, "Geeks");

        // 打印映射到控制台
        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中的元素是使用键进行索引的,因此可以通过为我们希望更改的键插入更新后的值来更改键的值。

// 演示更新Hashtable的Java程序

import java.io.*;
import java.util.*;

class UpdatesOnHashtable {
    public static void main(String args[])
    {

        // 初始化Hashtable
        Hashtable ht = new Hashtable();

        // 使用put方法插入元素
        ht.put(1, "Geeks");
        ht.put(2, "Geeks");
        ht.put(3, "Geeks");

        // 打印初始映射到控制台
        System.out.println("Initial Map " + ht);

        // 更新键2的值
        ht.put(2, "For");

        // 打印更新后的映射到控制台
        System.out.println("Updated Map " + ht);
    }
}

输出

Initial Map {3=Geeks, 2=Geeks, 1=Geeks}
Updated Map {3=Geeks, 2=For, 1=Geeks}

3. 移除元素: 为了从Map中移除一个元素,我们可以使用remove()方法。如果对应于该键的映射存在于Map中,则此方法取key值并删除该键的映射。

// 从Hashtable中删除映射的Java程序

import java.io.*;
import java.util.*;

class RemovingMappingsFromHashtable {

    public static void main(String args[])
    {
        // 初始化Hashtable
        Map ht = new Hashtable();

        // 使用put方法插入元素
        ht.put(1, "Geeks");
        ht.put(2, "For");
        ht.put(3, "Geeks");
        ht.put(4, "For");

        // 初始HashMap
        System.out.println("Initial map : " + ht);

        // 删除键为4的Map条目
        ht.remove(4);

        // 最终的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. 遍历Hashtable: 我们可以使用高级for循环对表进行迭代。以下是迭代Hashtable的示例。

//迭代Hashtable的Java程序

import java.util.*;

class IteratingHashtable {
    public static void main(String[] args)
    {

        // 初始化Hashtable
        Hashtable ht = new Hashtable();

        // 使用put方法插入元素
        ht.put(1, "Geeks");
        ht.put(2, "For");
        ht.put(3, "Geeks");

        // 使用for-each循环迭代Hashtable
        for (Map.Entry e : ht.entrySet())
            System.out.println(e.getKey() + " "
                               + e.getValue());
    }
}
// Java程序演示
// 遍历Hashtable
 
import java.util.Hashtable;
import java.util.Map;
 
public class IteratingHashtable {
    public static void main(String[] args)
    {
          // 创建Hashtable实例
        Hashtable<String, Integer> ht = new Hashtable<>();
 
          // 使用put方法添加元素
        ht.put("vishal", 10);
        ht.put("sachin", 30);
        ht.put("vaibhav", 20);
     
          // 使用增强型for循环遍历
        for (Map.Entry<String, Integer> e : ht.entrySet())
            System.out.println(e.getKey() + " "
                               + e.getValue());
    }
}

输出:

vaibhav 20
vishal 10
sachin 30

Hashtable的内部工作原理

Hashtable数据结构是一个存储键/值对的bucket数组。它使用 hashCode()方法 确定哪个bucket应该映射键/值对。
哈希函数帮助确定存储桶中给定键的位置。通常,哈希码是非负整数,对于相等的对象相等并且可能对于不相等的对象不相等。为确定两个对象是否相等,Hashtable使用equals()方法。

可能两个不相等的对象具有相同的哈希码。这称为 冲突 。为解决冲突,Hashtable使用列表数组。映射到单个bucket(数组索引)的键值对存储在列表中,并将列表引用存储在数组索引中。

Java中的Hashtable

Hashtable的方法

  • K – 映射中键的类型。
  • V – 映射中值的类型。

返回此映射中包含的值的集合视图。

在接口java.util.Map中声明的方法

方法 描述
forEach(BiConsumer<? super K, ? super V> action) 对此映射中的每个条目执行给定的操作,直到处理完所有条目或操作抛出异常。
getOrDefault(Object key, V 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) 用调用该条目上的给定函数的结果替换每个条目的值,直到处理完所有条目或该函数引发异常。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程