Hashtable 类

表示键/值对的集合,这些键/值对根据键的哈希代码进行组织。

**命名空间:**System.Collections
**程序集:**mscorlib(在 mscorlib.dll 中)

语法

声明
<SerializableAttribute> _
<ComVisibleAttribute(True)> _
Public Class Hashtable
    Implements IDictionary, ICollection, IEnumerable, ISerializable, _
    IDeserializationCallback, ICloneable
用法
Dim instance As Hashtable
[SerializableAttribute] 
[ComVisibleAttribute(true)] 
public class Hashtable : IDictionary, ICollection, IEnumerable, 
    ISerializable, IDeserializationCallback, ICloneable
[SerializableAttribute] 
[ComVisibleAttribute(true)] 
public ref class Hashtable : IDictionary, ICollection, IEnumerable, 
    ISerializable, IDeserializationCallback, ICloneable
/** @attribute SerializableAttribute() */ 
/** @attribute ComVisibleAttribute(true) */ 
public class Hashtable implements IDictionary, ICollection, 
    IEnumerable, ISerializable, IDeserializationCallback, ICloneable
SerializableAttribute 
ComVisibleAttribute(true) 
public class Hashtable implements IDictionary, ICollection, 
    IEnumerable, ISerializable, IDeserializationCallback, ICloneable

备注

每个元素都是一个存储在 DictionaryEntry 对象中的键/值对。键不能为 空引用(在 Visual Basic 中为 Nothing),但值可以。

要重写 Object.GetHashCode 方法(或 IHashCodeProvider 接口)和 Object.Equals 方法(或 IComparer 接口),需要有被 Hashtable 用作键的对象。方法和接口的实现必须以相同的方式处理大小写;否则,Hashtable 的行为可能不正确。例如,创建 Hashtable 时,您必须配合使用 CaseInsensitiveHashCodeProvider 类(或任何不区分大小写的 IHashCodeProvider 实现)和 CaseInsensitiveComparer 类(或任何不区分大小写的 IComparer 实现)。

此外,如果该键存在于 Hashtable 中,那么当使用相同参数调用这些方法时,这些方法必须生成相同的结果。还有一种方式是使用具有 IEqualityComparer 参数的 Hashtable 构造函数。如果键相等性只是引用相等性,则 Object.GetHashCodeObject.Equals 的继承实现将满足需要。

只要键对象用作 Hashtable 中的键,它们就必须是永远不变的。

当把某个元素添加到 Hashtable 时,将根据键的哈希代码将该元素放入存储桶中。该键的后续查找将使用键的哈希代码只在一个特定存储桶中搜索,这将大大减少为查找一个元素所需的键比较的次数。

Hashtable 的加载因子确定元素与存储桶的最大比率。加载因子越小,平均查找速度越快,但消耗的内存也增加。默认的加载因子 1.0 通常提供速度和大小之间的最佳平衡。当创建 Hashtable 时,也可以指定其他加载因子。

当向 Hashtable 添加元素时,Hashtable 的实际加载因子将增加。当实际加载因子达到指定的加载因子时,Hashtable 中存储桶的数目自动增加到大于当前 Hashtable 存储桶数两倍的最小质数。

Hashtable 中的每个键对象必须提供其自己的哈希函数,可通过调用 GetHash 访问该函数。但是,可将任何实现 IHashCodeProvider 的对象传递到 Hashtable 构造函数,而且该哈希函数用于该表中的所有对象。

Hashtable 的容量是 Hashtable 可拥有的元素数。Hashtable 的默认初始容量为零。随着向 Hashtable 中添加元素,容量通过重新分配按需自动增加。

C# 语言中的 foreach 语句(在 Visual Basic 中为 for each)需要集合中每个元素的类型。由于 Hashtable 的每个元素都是一个键/值对,因此元素类型既不是键的类型,也不是值的类型。而是 DictionaryEntry 类型。例如:

foreach (DictionaryEntry de in myHashtable) {...}
For Each de as DictionaryEntry In myHashtable
   ...
Next de

foreach 语句是对枚举数的包装,它只允许从集合中读取,不允许写入集合。

因为序列化和反序列化 Hashtable 的枚举数会使元素重新排序,所以不调用 Reset 方法就不能继续枚举。

示例

下面的示例说明如何对 Hashtable 创建、初始化并执行各种函数以及如何打印出其键和值。

Imports System
Imports System.Collections

Module Example

    Sub Main()

        ' Create a new hash table.
        '
        Dim openWith As New Hashtable()

        ' Add some elements to the hash table. There are no 
        ' duplicate keys, but some of the values are duplicates.
        openWith.Add("txt", "notepad.exe")
        openWith.Add("bmp", "paint.exe")
        openWith.Add("dib", "paint.exe")
        openWith.Add("rtf", "wordpad.exe")

        ' The Add method throws an exception if the new key is 
        ' already in the hash table.
        Try
            openWith.Add("txt", "winword.exe")
        Catch
            Console.WriteLine("An element with Key = ""txt"" already exists.")
        End Try

        ' The Item property is the default property, so you 
        ' can omit its name when accessing elements. 
        Console.WriteLine("For key = ""rtf"", value = {0}.", _
            openWith("rtf"))

        ' The default Item property can be used to change the value
        ' associated with a key.
        openWith("rtf") = "winword.exe"
        Console.WriteLine("For key = ""rtf"", value = {0}.", _
            openWith("rtf"))

        ' If a key does not exist, setting the default Item property
        ' for that key adds a new key/value pair.
        openWith("doc") = "winword.exe"

        ' The default Item property throws an exception if the requested
        ' key is not in the hash table.
        Try
            Console.WriteLine("For key = ""tif"", value = {0}.", _
                openWith("tif"))
        Catch
            Console.WriteLine("Key = ""tif"" is not found.")
        End Try

        ' ContainsKey can be used to test keys before inserting 
        ' them.
        If Not openWith.ContainsKey("ht") Then
            openWith.Add("ht", "hypertrm.exe")
            Console.WriteLine("Value added for key = ""ht"": {0}", _
                openWith("ht"))
        End If

        ' When you use foreach to enumerate hash table elements,
        ' the elements are retrieved as KeyValuePair objects.
        Console.WriteLine()
        For Each de As DictionaryEntry In openWith
            Console.WriteLine("Key = {0}, Value = {1}", _
                de.Key, de.Value)
        Next de

        ' To get the values alone, use the Values property.
        Dim valueColl As ICollection = openWith.Values

        ' The elements of the ValueCollection are strongly typed
        ' with the type that was specified for hash table values.
        Console.WriteLine()
        For Each s As String In valueColl
            Console.WriteLine("Value = {0}", s)
        Next s

        ' To get the keys alone, use the Keys property.
        Dim keyColl As ICollection = openWith.Keys

        ' The elements of the KeyCollection are strongly typed
        ' with the type that was specified for hash table keys.
        Console.WriteLine()
        For Each s As String In keyColl
            Console.WriteLine("Key = {0}", s)
        Next s

        ' Use the Remove method to remove a key/value pair.
        Console.WriteLine(vbLf + "Remove(""doc"")")
        openWith.Remove("doc")

        If Not openWith.ContainsKey("doc") Then
            Console.WriteLine("Key ""doc"" is not found.")
        End If

    End Sub

End Module

' This code example produces the following output:
'
'An element with Key = "txt" already exists.
'For key = "rtf", value = wordpad.exe.
'For key = "rtf", value = winword.exe.
'For key = "tif", value = .
'Value added for key = "ht": hypertrm.exe
'
'Key = dib, Value = paint.exe
'Key = txt, Value = notepad.exe
'Key = ht, Value = hypertrm.exe
'Key = bmp, Value = paint.exe
'Key = rtf, Value = winword.exe
'Key = doc, Value = winword.exe
'
'Value = paint.exe
'Value = notepad.exe
'Value = hypertrm.exe
'Value = paint.exe
'Value = winword.exe
'Value = winword.exe
'
'Key = dib
'Key = txt
'Key = ht
'Key = bmp
'Key = rtf
'Key = doc
'
'Remove("doc")
'Key "doc" is not found.
using System;
using System.Collections;

class Example
{
    public static void Main()
    {
        // Create a new hash table.
        //
        Hashtable openWith = new Hashtable();
        
        // Add some elements to the hash table. There are no 
        // duplicate keys, but some of the values are duplicates.
        openWith.Add("txt", "notepad.exe");
        openWith.Add("bmp", "paint.exe");
        openWith.Add("dib", "paint.exe");
        openWith.Add("rtf", "wordpad.exe");
        
        // The Add method throws an exception if the new key is 
        // already in the hash table.
        try
        {
            openWith.Add("txt", "winword.exe");
        }
        catch
        {
            Console.WriteLine("An element with Key = \"txt\" already exists.");
        }

        // The Item property is the default property, so you 
        // can omit its name when accessing elements. 
        Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);
        
        // The default Item property can be used to change the value
        // associated with a key.
        openWith["rtf"] = "winword.exe";
        Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);
        
        // If a key does not exist, setting the default Item property
        // for that key adds a new key/value pair.
        openWith["doc"] = "winword.exe";

        // The default Item property throws an exception if the requested
        // key is not in the hash table.
        try
        {
            Console.WriteLine("For key = \"tif\", value = {0}.", openWith["tif"]);
        }
        catch
        {
            Console.WriteLine("Key = \"tif\" is not found.");
        }

        // ContainsKey can be used to test keys before inserting 
        // them.
        if (!openWith.ContainsKey("ht"))
        {
            openWith.Add("ht", "hypertrm.exe");
            Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]);
        }

        // When you use foreach to enumerate hash table elements,
        // the elements are retrieved as KeyValuePair objects.
        Console.WriteLine();
        foreach( DictionaryEntry de in openWith )
        {
            Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
        }

        // To get the values alone, use the Values property.
        ICollection valueColl = openWith.Values;
        
        // The elements of the ValueCollection are strongly typed
        // with the type that was specified for hash table values.
        Console.WriteLine();
        foreach( string s in valueColl )
        {
            Console.WriteLine("Value = {0}", s);
        }

        // To get the keys alone, use the Keys property.
        ICollection keyColl = openWith.Keys;
        
        // The elements of the KeyCollection are strongly typed
        // with the type that was specified for hash table keys.
        Console.WriteLine();
        foreach( string s in keyColl )
        {
            Console.WriteLine("Key = {0}", s);
        }

        // Use the Remove method to remove a key/value pair.
        Console.WriteLine("\nRemove(\"doc\")");
        openWith.Remove("doc");
        
        if (!openWith.ContainsKey("doc"))
        {
            Console.WriteLine("Key \"doc\" is not found.");
        }
    }
}

/* This code example produces the following output:

An element with Key = "txt" already exists.
For key = "rtf", value = wordpad.exe.
For key = "rtf", value = winword.exe.
For key = "tif", value = .
Value added for key = "ht": hypertrm.exe

Key = dib, Value = paint.exe
Key = txt, Value = notepad.exe
Key = ht, Value = hypertrm.exe
Key = bmp, Value = paint.exe
Key = rtf, Value = winword.exe
Key = doc, Value = winword.exe

Value = paint.exe
Value = notepad.exe
Value = hypertrm.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe

Key = dib
Key = txt
Key = ht
Key = bmp
Key = rtf
Key = doc

Remove("doc")
Key "doc" is not found.
 */

继承层次结构

System.Object
  System.Collections.Hashtable
     System.Configuration.SettingsAttributeDictionary
     System.Configuration.SettingsContext
     System.Data.PropertyCollection

线程安全

Hashtable 是线程安全的,可由多个读取器线程或一个写入线程使用。多线程使用时,如果任何一个线程执行写入(更新)操作,它都不是线程安全的。若要支持多个编写器,如果没有任何线程在读取 Hashtable 对象,则对 Hashtable 的所有操作都必须通过 Synchronized 方法返回的包装完成。

从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。

平台

Windows 98、Windows 2000 SP4、Windows CE、Windows Millennium Edition、Windows Mobile for Pocket PC、Windows Mobile for Smartphone、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition

.NET Framework 并不是对每个平台的所有版本都提供支持。有关受支持版本的列表,请参见系统要求

版本信息

.NET Framework

受以下版本支持:2.0、1.1、1.0

.NET Compact Framework

受以下版本支持:2.0、1.0

请参见

参考

Hashtable 成员
System.Collections 命名空间
IDictionary
IHashCodeProvider
Object.GetHashCode
Object.Equals
DictionaryEntry 结构
System.Collections.Generic.Dictionary
IEqualityComparer