`
cdragon
  • 浏览: 76989 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

effective hierarchy(一)之 从array说起(4)

阅读更多

回顾:上一节中,我们看到了数组列表、队列与栈,从边界上突破了数组的局限。下面继续来看实用的哈希表。

 

MSDN:c#2.0

 

HashTable:

1.基础

(1)表示一系列(collection)的键-值(key-value)对,由键的哈希代码(hash code)来组织。它的语法为

        [SerializableAttribute]
        [ComVisibleAttribute(true)]
        public class Hashtable : IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback, ICloneable

 

 (2)Hashtable的每个元素都是以DictionaryEntry对象储存的键值对;

 (3)值可以为空引用,但键不能是空引用;

 (4)在Hashtable中,作为键的键对象不能被修改(immutable);

 (5)通过Add()方法添加元素时,基于键的哈希码,元素被置于带柄的桶(bucket)中;随后对该键的查找,是使用该键的哈希码只在特定的桶中搜索(search),将大大减少为查找一个元素所需要的键比较的次数;

 (6)Hashtable的每个键对象,必须提供可通过GetHash访问调用的自有哈希函数(hash function);但是,任意实现了IHashCodeProvider的对象都可以传递到Hashtable构建器,该函数可用于表(table)中的所有对象;

(7)Hashtable的容量是它所能支持的元素数量;增加容量的时候,容量会重新分配,自动增加;

(8)因为键可以被继承,从而改变行为,所以使用Equals方法进行的比较并不能保证(guarante)键的绝对唯一性(absolute uniqueness)。

 

2.遍历

(1)使用foreach时,对集合中每个元素的类型提出要求;因为Hashtable的每个元素都是键值对,所以它的类型不是键对象的类型也不是值的类型。这是一个DictionaryEntry结构(struct);如foreach (DictionaryEntry de in myHashtable) {...};

(2)foreach语句是枚举器(enumerator)的包装者(wrapper),只允许从集合读出而不允许写入;

(3)因为对一个枚举器进行序列化(serializing)和解除序列化(deserializing)会导致元素被记录(recordded),必须使用Reset方法来使枚举继续进行。

 

3.载入因子

(1)元素放到桶中的最大比率(maximum ratio)是由Hashtable的载入因子(load factor)决定;

(2)载入因子越小,平均查找时间越短,同时更消耗内存;

(3)缺省的载入因子是1.0,一般地,该值在速度和大小之间能够保持最好的平衡;创建哈希表时,可指另外的载入因子;

(4)元素加到Hashtable时,实际的载入因子会增加(increase),当实际载入因子达到指定的载入因子时,哈希表桶的数量自动增加,增加到大于哈希表当前桶数的两倍的最小质数(prime number);

 

4.方法重写

(1)作为Hashtable键的对象,需要重写(override)对象类的Obejct.GetHashCode()方法(或IHashCodeProvider接口)以及Object.Equals()方法(或IComparer接口);

(2)无论是重写方法还是接口,都必须以相同的方式控制大小写敏感性(handle case sentivity),否则,可能导致Hashtable错误地行为(behave);如,在创建Hashtable的时候,必须同CaseInsensitiveComparer类(或任意大小写不敏感的IComparer实现)一起使用CaseInsensitiveHashCodeProvider类(或任意大小写不敏感的IHashCodeProvider实现);

(3)另外,当键存在(exist)于Hashtable时,这些方法调用相同的参数必须产生相同的结果;一种可行的替代方式是使用IEqualityComparer参数的构建器;如果键相等性(equality)仅仅是引用相等性(reference equality),继承下来的Object.GetHashCode()和Object.Equals()方法就足够了;

 

//主要用途示例

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";

        // 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.
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.
 */

 

-------------------------------------------------------------------------------------------------------------------- 

小结:从本节,我们看到一个基于数组特征的集大成者。在实际使用中,应根据情况对待数组相关的不同概念。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics