hashtable排序问题

对于Hashtable在我的上篇博客中有提到,是用在了事务处理中,向sqlhelper传递参数,这个用的很巧妙不知道大家有没有进一步的研究,但是为什么现在需要用到Hashtable的排序呢。大家跟着我想这样的一个场景,现在需要注册一个新用户,注册用户的时候需要有如下的业务逻辑:每个用户拥有或多张卡,注册用户的时候需要对卡进行一定金额的充值。

 

一、业务表分析:

对于这个业务逻辑我们建立的关系表需要有三张,1.用户信息表,用于保存用户的基本信息;2.卡信息表,用于保存卡的基本信息;3.充值记录表,用于保存充值记录信息。当然考虑数据库建立的三范式,我们还需要保证这三张表具有主外键的关系。用一张数据库关系图来表示:

二、与事务机制的联系:

         当然我们会想到这“三件”事必须同时完成或同时不完成,他们的这种关系就组成了一个事务操作,而这个要求即事务的原子性。

三、为什么要对Hashtable排序:

要实现这样的需求,还需要满足的操作要求:三张表的插入顺序是:用户表——卡表——充值表。

对于Hashtable有一定了解的人都知道Hashtable的一个重要的特点就是排序无序的。

对于这个无序的说明有这样的一个例子:

 

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     Hashtable ht = new Hashtable();
  4.     ht.Add(“key1”, “value1”);
  5.      ht.Add(“key2”, “value2”);
  6.     ht.Add(“key3”, “value3”);
  7.     ht.Add(“key4”, “value4”);
  8.      ht.Add(“key5”, “value5”);
  9.      foreach (string str in ht.Keys)
  10.      {
  11.         Console.WriteLine(str + “:” + ht[str]);
  12.     }
  13. }

 

运行的结果:

通过这个小例子就可以理解了哈希表的无序性。那我们怎么保证程序按照我们想要的顺序在sqlhelper中逐个的执行呢。(这个执行的代码看上篇博客)我们就需要Hashtable进行排序了。

 

四、排序的方法:

这里我主要给大家介绍3种方法:

 

         1.我按什么顺序加进去就按什么顺序输出:

[vb][/vb] view plaincopyprint?

  1. public class NoSortHashTable : Hashtable
  2. {
  3.     private ArrayList list = new ArrayList();
  4.     public override void Add(object key, object value)
  5.     {
  6.         base.Add(key, value);
  7.         list.Add(key);
  8.     }
  9.     public override void Clear()
  10.     {
  11.         base.Clear();
  12.         list.Clear();
  13.     }
  14.     public override void Remove(object key)
  15.     {
  16.         base.Remove(key);
  17.         list.Remove(key);
  18.     }
  19.     public override ICollection Keys
  20.     {
  21.         get
  22.         {
  23.             return list;
  24.         }
  25.     }
  26. }

这里注意:ArrayList是不排序的(添加的顺序就是输出的顺序)。让它和hashtable结合不就实现这种功能的吗?这样继承了Hashtable具有Hashtable的丰富功能,又满足ArrayList不排序的功能。满足我们的要求。

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     NoSortHashTable ht = new NoSortHashTable();
  4.     ht.Add(“key1”, “value1”);
  5.     ht.Add(“key2”, “value2”);
  6.     ht.Add(“key3”, “value3”);
  7.     ht.Add(“key4”, “value4”);
  8.     ht.Add(“key5”, “value5”);
  9.     foreach (string str in ht.Keys)
  10.     {
  11.         Console.WriteLine(str + “:” + ht[str]);
  12.     }
  13. }

这样一运行就满足我的要求了:

       成功了!

 

        2.我按Hashtable中键的大小顺序进行排序

实际上是按照每一个字符的ASCII的值就行排序的。从左到右比较每个字符的Ascii的值,直到满足两个字符的ASCII的值不同即停止比较

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     Hashtable ht = new Hashtable();
  4.     ht.Add(“ee”, “value1”);
  5.     ht.Add(“dd”, “value2”);
  6.     ht.Add(“cc”, “value3”);
  7.     ht.Add(“bb”, “value4”);
  8.     ht.Add(“aa”, “value5”);
  9.     ArrayList list = new ArrayList(ht.Keys);
  10.     list.Sort();
  11.     foreach (string str in list)
  12.     {
  13.         Console.WriteLine(str+”:”+ht[str]);
  14.     }
  15. }

运行效果:

        成功了!

 

        3.我按Hashtable中的值得大小就行排序

原理同上:实际上是按照每一个字符的ASCII的值就行排序的。从左到右比较每个字符的Ascii的值,直到满足两个字符的ASCII的值不同即停止比较

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     Hashtable ht = new Hashtable();
  4.     ht.Add(“a”, “3”);
  5.     ht.Add(“b”, “4”);
  6.     ht.Add(“c”, “2”);
  7.     ht.Add(“d”, “1”);
  8.     ArrayList list = new ArrayList(ht.Values);
  9.     list.Sort();
  10.     foreach (string svalue in list)
  11.     {
  12.         IDictionaryEnumerator ide = ht.GetEnumerator();
  13.         while (ide.MoveNext())
  14.         {
  15.             if (ide.Value.ToString() == svalue)
  16.             {
  17.                 Console.WriteLine(ide.Key + “:” + svalue);
  18.             }
  19.         }
  20.     }
  21. }

运行效果:

成功了!

 

五、总结:

 

针对第二,第三,我们可以看出来了通过下面的这个方法把Hashtable的键(keys)或值(values)转换成Arraylist.

ArrayList list = new ArrayList(ht.Values);

ArrayList list=  new ArrayList(ht.Keys);

这样就可以把Hashtable的排序转换成ArrayList的排序了!

另外ArrayList提供的很多方法排序:

ArrayList.Sort()——————-按字符的Ascii的值排序

ArrayList.Reverse()—————反转数组

等还多ArrayList方法。如果都不满足你要的排序功能的话,那就自己针对ArrayList这个数组写算法就能对ArrayList排序,ArrayList排序也就完成了Hashtable的排序。

 

六、重点说明:

另外,需要说明一点,上面的排序是不严谨的,有值相等时会有重复输出 。

例如:

 

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     Hashtable hs = new Hashtable();
  4.     hs.Add(5, 40);
  5.     hs.Add(4, 20);
  6.     hs.Add(3, 20);
  7.     hs.Add(2, 15);
  8.     hs.Add(1, 5);
  9.     ArrayList als = new ArrayList(hs.Values);
  10.     als.Sort();
  11.     foreach (object ob in als)
  12.     {
  13.         IDictionaryEnumerator ide = hs.GetEnumerator();
  14.         while (ide.MoveNext())
  15.         {
  16.             if (ide.Value.ToString() == ob.ToString())
  17.             Console.WriteLine(ide.Key.ToString() + “:” + ob.ToString());
  18.         }
  19.     }
  20. }

运行结果为:

引起这个问题主要是那hashtable中允许有重复的值引起的。如果要想解决这个问题的话,在转换成ArrayList时候需要把重复的value去掉。(key不允许重复就不会出现)

可以将程序改为:

 

[vb][/vb] view plaincopyprint?

  1. public static void Main()
  2. {
  3.     Hashtable ht = new Hashtable();
  4.     ht.Add(5, 40);
  5.     ht.Add(4, 20);
  6.     ht.Add(3, 20);
  7.     ht.Add(2, 15);
  8.     ht.Add(1, 5);
  9.     ArrayList listTemp = new ArrayList(ht.Values);
  10.     ArrayList list = new ArrayList();
  11.     foreach (object value in listTemp)
  12.     {
  13.         if (!list.Contains(value))
  14.         {
  15.             list.Add(value);
  16.         }
  17.     }
  18.     list.Sort();
  19.     foreach (object obj in list)
  20.     {
  21.         IDictionaryEnumerator ide = ht.GetEnumerator();
  22.         while (ide.MoveNext())
  23.         {
  24.             if (ide.Value.ToString() == obj.ToString())
  25.             {
  26.                 Console.WriteLine(ide.Key.ToString() + “:” + obj.ToString());
  27.             }
  28.         }
  29.     }
  30. }

运行结果为:

成功了!

标签