Hashtable

下面是个简单的例子对ArrayList和Hashtable做了个对比:

 1 int i;
 2 System.Collections.Hashtable hs = new System.Collections.Hashtable();
 3 System.Collections.ArrayList arr = new System.Collections.ArrayList();
 4
 5 long StartTime  = DateTime.Now.Ticks;
 6 for ( i = 0 ; i < 10000 ; i ++ )  {
 7     arr.Add(i);
 8 }
 9 long EndTime  = DateTime.Now.Ticks;
10 Console.WriteLine( "ArryList添加执行时间:" + (EndTime-StartTime) );
11
12 StartTime  = DateTime.Now.Ticks;
13 for ( i = 0 ; i < 10000 ; i ++ ) 
14 {
15     hs.Add(i,"我是"+i);
16 }
17 EndTime  = DateTime.Now.Ticks;
18 Console.WriteLine( "Hashtable添加执行时间:" + (EndTime-StartTime) );
19
20 StartTime  = DateTime.Now.Ticks;
21 for ( i = 0 ; i < 10000 ; i ++ ) 
22 {
23     arr.Contains(i) ;
24 }
25 EndTime  = DateTime.Now.Ticks;
26 Console.WriteLine( "ArryList查找执行时间:" + (EndTime-StartTime) );
27
28 StartTime  = DateTime.Now.Ticks;
29 for ( i = 0 ; i < 10000 ; i ++ ) 
30 {
31         hs.Contains(i) ;
32 }
33 EndTime  = DateTime.Now.Ticks;
34 Console.WriteLine( "Hashtable查找执行时间:" + (EndTime-StartTime) );
35
36 StartTime  = DateTime.Now.Ticks;
37 for ( i = 0 ; i < 10000 ; i ++ ) 
38 {
39     arr.Remove(i) ;
40 }
41 EndTime  = DateTime.Now.Ticks;
42 Console.WriteLine( "ArryList删除执行时间:" + (EndTime-StartTime) );
43
44 StartTime  = DateTime.Now.Ticks;
45 for ( i = 0 ; i < 10000 ; i ++ ) 
46 {
47     hs.Remove(i) ;
48 }
49 EndTime  = DateTime.Now.Ticks;
50 Console.WriteLine( "Hashtable删除执行时间:" + (EndTime-StartTime) );


上面的代码执行结果:

1 ArryList添加执行时间:0
2 Hashtable添加执行时间:300432
3 ArryList查找执行时间:10214688
4 Hashtable查找执行时间:0
5 ArryList查找执行时间:701008
6 Hashtable查找执行时间:0


结果可以说明,使用正确的容器对程序的优化是至关重要的..而选择正确的容器,也完全在于对容器的了解和对业务的熟悉..这里需要注意一点,开头的地方说添加也很快,但是Hashtable的添加要比ArrayList慢很多..主要是因为Hashtable要对key做一系列的索引算法,也是为了更好的查找和删除做的准备工作... 另外这里提示一点,就是在Hashtable初始化的时候可以给它指定默认容量和加载因子,其中加载因子越小,则平均查找速度就越快,但内存消耗就越大..默认的容量是16,加载因子是1..加载因子的取值范围是0.1-1之间..可以根据你的数据大小适当的调整容量和加载因子来提高速度..

 1 System.Collections.Hashtable hs = new System.Collections.Hashtable();
 2 int i;
 3 long StartTime  = DateTime.Now.Ticks;
 4 for ( i = 0; i < 10000;i ++ ) 
 5 {
 6     hs.Add( i,"我是"+i );
 7 }
 8 long EndTime  = DateTime.Now.Ticks;
 9 Console.WriteLine( "hs添加执行时间:" + (EndTime-StartTime) );
10
11 System.Collections.Hashtable hs2 = new System.Collections.Hashtable(10001,0.3f);
12 StartTime  = DateTime.Now.Ticks;
13 for ( i = 0; i < 10000;i ++ ) 
14 {
15     hs2.Add( i,"我是"+i );
16 }
17 EndTime  = DateTime.Now.Ticks;
18 Console.WriteLine( "hs2添加执行时间:" + (EndTime-StartTime) );


上面的代码执行结果:

1 hs添加执行时间:200288
2 hs2添加执行时间:100188

这个结果,经过我测试,在你i<40000的时候,是明显的,但是i>40000的时候,效率就很差了.甚至是不如默认的...并且根据数据的不同,这个结果都会有偏差,不过数据量保持在某个值(这个值也是很变化的)以下的时候,调整加载因子比默认的速度还是要快点的...


如果你传递给Hashtable的key是Class,而如何保证key的唯一呢??因为Hashtable还是用到了HashCode做为验证唯一性,所以你还要在你的类覆写GetHashCode(),并且也要重写Equals()以判断是否相等..具体问题可以看给你的类重写Equals--检测Class是否相等 .基础的东西这里都有说明..尤其是后面的回复..可以多看看..

现在来看Hashtable的具体实现,首先你添加一对键/值后,会将键和对象的引用放入存储桶,Hashtable的键索引是按key对象的GetHashCode方法计算的,查找的时候也是用查找的键与存储的键对比,对比的方法还是要依赖Equals!!这个过程也说明了,为什么覆写了GetHashCode之后也要覆盖Equals了..看代码:

 1 //=============  用户类   ==================
 2 public class User
 3 {
 4     private string name = null;
 5     public User(string name)
 6      {
 7         this.name = name;
 8     }
 9    
10     public override string ToString()    //覆写ToString()
11      {
12         return name;
13     }
14    
15     //这里因为name是不重复的,所以获取name的HashCode,作为
16     public override int GetHashCode()   
17      {
18         return ToString().GetHashCode();
19     }
20    
21     /**//// <summary>
22     ///        覆写Equals,判断对象是否具有相同的
23     /// </summary>
24     /// <param name="obj"></param>
25     /// <returns></returns>
26     public override bool Equals(object obj)
27      {
28         User u = obj as User;   
29         if ( u == null )            //如果不能转换为当前Class,则返回false
30             return false;
31         if ( this.name == u.name && this.ToString() == u.ToString() )
32             return true;
33        
34         return false;
35     }
36    
37 }
38
39 // ============  对应用户的信息  ==============
40 public class UserInfo
41 {
42     private User u;
43     public UserInfo(User us)
44      {
45         this.u = us;
46     }
47    
48     public override string ToString()
49      {
50         return u.ToString() + "的信息";
51     }
52    
53 }
54
55 //==========  测试代码 Main  ==================
56 static void Main(string[] args)
57 {
58     User u1 = new User("小李");
59     User u2 = new User("小王");
60     UserInfo info1 = new UserInfo(u1);
61     UserInfo info2 = new UserInfo(u2);
62     System.Collections.Hashtable hs = new System.Collections.Hashtable();
63    
64     hs.Add( u1,info1 );
65     hs.Add( u2,info2 );
66    
67     User u3 = new User("小李");
68     UserInfo info3 = new UserInfo(u1);
69     User u4 = new User("小王");
70    
71     Console.WriteLine( hs[u3] );
72     Console.WriteLine( hs[u4] );
73     try  {
74         hs.Add( u3, info3);
75     }catch(ArgumentException ee)  {
76         Console.WriteLine( ee.Message );
77     }
78    
79 }

上面的代码实例化了四个类,其中两个小王,两个小李,先添加小李1和小王1到Hashtable中,然后用新的小王2和小李2进行查找Hashtable,因为作为键的User类重写了GetHashCode和Equals,并且实例的时候也都是用的小王和小李,并且他们的string.GetHashCode是一样的..所以会被找到...最后程序又试图添加小李2到Hashtable中,但是因为里面已经存在了一个相同的key.GetHashCode,所以添加导致了异常...上面的输出结果是:

1 小李的信息
2 小王的信息
3 已添加项。字典中的键: “小李”  所添加的键: “小李”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值