梦想与现实的落差,就是我们离成功的距离!!

博客园 首页 新随笔 联系 订阅 管理
  34 Posts :: 3 Stories :: 345 Comments :: 11 Trackbacks
不知道把这么一篇不入流的东西放在首页有碍观瞻,但就算是新手也一般是浏览首页,我的目的也是希望给一些碰到类似问题的新手提供点帮助,也希望得到高手的指点。
先看下面的代码

using System;
using System.Collections;

namespace NoSortHashtable
{
    
/// <summary>
    
/// Summary description for Class1.
    
/// </summary>
    class Class1
    {
        
/// <summary>
        
/// The main entry point for the application.
        
/// </summary>
        [STAThread]
        
static void Main(string[] args)
        {
            Hashtable hashTable 
= new Hashtable();

            hashTable.Add(
"hunan","changsha");
            hashTable.Add(
"beijing","beijing");
            hashTable.Add(
"anhui","hefei");
            hashTable.Add(
"sichuan","chengdu");
            
foreach(string str in hashTable.Keys)
            {
                Console.WriteLine(str 
+ " : " + hashTable[str]);
            }

        }
    }
}

打印的结果是:
    anhui : hefei
    hunan : changsha
    sichuan : chengdu
    beijing : beijing

当然,产生这个结果的原因大家都知道,Hashtable内部的排序机制使然,但我现在就是不想排序,我按什么顺序输入的,就想它再怎么给我输出,怎么办?去Google酷了一下,却因为不知道使用什么关键字去酷,结果没有酷出好的相关问题来。
我想到,ArrayList是不排序的啊,那是不是让ArrayList和Hastable配成良缘,那么它们的结晶就是我想要的呢,既有Hashtable的丰富功能,又可以满足我的BT的要求(不排序),动手了。
using System;
using System.Collections;

namespace NoSortHashtable
{
    
/// <summary>
    
/// Summary description for NoSortedHashtable.
    
/// </summary>

    public class NoSortHashtable : Hashtable
    
{
        
private ArrayList keys = new ArrayList();

        
public NoSortHashtable()
        
{
        }

        

        
public override void Add(object key, object value)
        
{
            
base.Add (key, value);
            keys.Add (key);
        }


        
public override ICollection Keys
        
{
            
get
            
{
                
return keys;
            }

        }


        
public override void Clear()
        
{
            
base.Clear ();
            keys.Clear ();
        }


        
public override void Remove(object key)
        
{
            
base.Remove (key);
            keys.Remove    (key);
        }

        
public override IDictionaryEnumerator GetEnumerator()
        
{
            
return base.GetEnumerator ();
        }


    }

}


再试
            hashTable = new NoSortHashtable();

            hashTable.Add(
"hunan","changsha");
            hashTable.Add(
"beijing","beijing");
            hashTable.Add(
"anhui","hefei");
            hashTable.Add(
"sichuan","chengdu");
            
foreach(string str in hashTable.Keys)
            {
                Console.WriteLine(str 
+ " : " + hashTable[str]);
            }

打印结果:
    hunan : changsha
    beijing : beijing
    anhui : hefei
    sichuan : chengdu


问题解决!!
应该很早之前就有人这么解决,只是我不知道而已,高手也应该有更好的办法,只是我想不到而已!
见笑,见谅!
posted on 2006-01-05 11:56 叶漂 阅读(8841) 评论(42)  编辑 收藏 所属分类: 经验小谈

评论

#1楼  2006-01-05 12:26 quitgame      
高手啊

有一点遗憾
就是把 Hashtable 的几个构造函数弄丢了
建议使用装饰器模式解决此问题
  回复  引用  查看    

#2楼  2006-01-05 12:31 linkin      
try NameValueCollection
  回复  引用  查看    

#3楼  2006-01-05 12:55 kiler      
用用sortedlist吧,可以排序
  回复  引用  查看    

#4楼  2006-01-05 13:08 leafyoung      
System.Collections.Specialized.ListDictionary 这个应该可以满足要求,只要数据量不太大
  回复  引用  查看    

#5楼 [楼主] 2006-01-05 13:13 叶漂      
to kiler
sortedlist 是不行的,我就是不要排序,它也是自动排序的
  回复  引用  查看    

#6楼 [楼主] 2006-01-05 13:13 叶漂      
多谢大家的指点
  回复  引用  查看    

good
  回复  引用  查看    

#8楼  2006-01-05 17:34 dali [未注册用户]
原来Hashtable是自动排序的呀
  回复  引用    

#9楼  2006-01-05 18:28 FantasySoft      
Hashtable中元素的序列应该是随机的哦~~~
  回复  引用  查看    

#10楼 [楼主] 2006-01-05 19:10 叶漂      
不是随机排序的,是在内部通过某种机制对Key进行排序,在外面是干涉不到的,所以我们不能直接对Hashtable排序的,当然通过某些变通的方法也可以让它按字母顺序排序
  回复  引用  查看    

#11楼  2006-01-06 08:30 quitgame      
@FantasySoft
Hashtable 内的元素 基本是按 哈希值 排序的,但如果遇到碰撞,会执行相应的散列
^^
  回复  引用  查看    

#12楼  2006-01-06 08:47 DrkBreeze's Bolg      
用Queue 行不行啊, 这个好像是一个先进先出的队列
  回复  引用  查看    

#13楼  2006-01-06 08:57 Pharaoh      
很久以前写的一个不排序和可以重复Key的SortedList,可以参考一下。http://pharaoh.cnblogs.com/archive/2005/05/16/156202.html
  回复  引用  查看    

#14楼  2006-01-06 09:19 FantasySoft      
虽然没有玩过C#中的Hashtable,但是我相信Hashtable的实现应该都是类似的。如果Hashtable以一个固定的规则排序,那么也就是说增加key/value pair的顺序不会影响最终的输出结果。但是事实上并非如此,改变了以下四句话的顺序,会影响最终的输出结果的:
hashTable.Add("hunan","changsha");
hashTable.Add("beijing","beijing");
hashTable.Add("anhui","hefei");
hashTable.Add("sichuan","chengdu");

也许我妄言是随机排序有点武断了,但既然是排序,就应该与增加key/value pair的次序是无关的,否则又怎能算排序呢?

我的基础知识比较薄弱,如果说错了,请各位多多批评。

  回复  引用  查看    

#15楼  2006-01-06 09:56 quitgame      
@FantasySoft
我查了一下MSDN 又试了一下
1 我前面所述的 "基本是按 哈希值 排序的" 是不正确的,只能说跟Hash值有关
2 并没有发现 因为插入的顺序不同而导致输出的顺序不同
3 输出的顺序会因为 存储桶的大小而改变
比如说 ht = new Hashtable(10) ; 和 ht = new Hashtable(100) ; 的时候会出两种不同的输出结果
考虑到简单的Hash算法 一般是这样的 存储位置 = x.GetHashCode() % 桶大小 , 假设Hashtable 的输出枚举是按照存储位置进行的,则输出结果会随初始桶的大小而改变是正确的

请多多指教 :)

  回复  引用  查看    

#16楼  2006-01-06 10:19 FantasySoft      
To quitgame: 所谓输出的变化,是值key的顺序发生了变化。诚然,由key得出的hashcode由始至终都是一样的,但问题是通过Hashtable.Keys返回的key序列却会根据插入的顺序而发生变化。见以下测试结果:
1. 与原文一样的插入顺序:
hashTable.Add("hunan","changsha");
hashTable.Add("beijing","beijing");
hashTable.Add("anhui","hefei");
hashTable.Add("sichuan","chengdu");

结果是:anhui : hefei
hunan : changsha
sichuan : chengdu
beijing : beijing

2. 改变了插入顺序:
hashTable.Add("anhui","hefei");
hashTable.Add("beijing","beijing");
hashTable.Add("hunan","changsha");
hashTable.Add("sichuan","chengdu");

结果是:hunan : changsha
anhui : hefei
beijing : beijing
sichuan : chengdu
  回复  引用  查看    

#17楼  2006-01-06 10:27 quitgame      
@FantasySoft
不知你的全部代码?我的是
Hashtable hashTable =new Hashtable();

hashTable.Add(
"anhui","hefei");
hashTable.Add(
"beijing","beijing");
hashTable.Add(
"hunan","changsha");
hashTable.Add(
"sichuan","chengdu");

foreach(string s in hashTable.Keys)
{
Console.WriteLine(hashTable[s]) ;
}

得出的结果始终是 hefei changsha chengdu beijing
我的是 fw1.1 的结果 :)


  回复  引用  查看    

#18楼  2006-01-06 10:30 FantasySoft      
To quitgame: 对于你说的第三点,hashtable的初始长度会用于计算某一个key/value的index,因此改变了初始长度,index也就发生了变化,那么key的序列发生变化也在情理之中。
  回复  引用  查看    

#19楼  2006-01-06 10:33 FantasySoft      
To quitgame:就是把楼主的代码拿来修改啊,改变代码中的Add方法的顺序就会得到不同的输出结果。难道我们的结果不一样? FT~~~

BTW:我用的.NET 2.0,而且我也在Java上测试过了,相同的结果。
  回复  引用  查看    

#20楼  2006-01-06 14:25 FantasySoft      

To quitgame: 我写一篇Post——解读Hashtable来说明这个问题的。

谢谢你,还有叶漂兄,给了我思考与反思的机会。


  回复  引用  查看    

#21楼  2006-01-06 15:23 活靶子.Net      
SortList可以用阿
  回复  引用  查看    

#22楼 [楼主] 2006-01-06 15:33 叶漂      
没想到我的一篇小文引发了我们对hashtable的深入讨论,让我明白了一句话,“鼓不敲不响,话不讲不明”,也怪不得那么多爱开研讨会了。
另外郑重申明,本人是GG,不是MM,这么MM是我GF而已
  回复  引用  查看    

#23楼  2006-01-06 17:58 FantasySoft      
叶漂兄,不好意思,不好意思~~ 我已经改过来了。
  回复  引用  查看    

#24楼  2006-01-13 15:17 xiaoma [未注册用户]
感谢楼主分享,只是有一点小弟还不明白:哈希表就是为了加速检索而进行优化的字典,像您文中的实现方式好像把他的优点全部抹杀了,是不是呀?是否可以考虑直接实现IDictionary接口来实现您所要求的功能呀?(注:本人是个菜鸟,有什么不妥还望指正)
  回复  引用    

#25楼 [楼主] 2006-01-14 17:56 叶漂      
xiaoma
的确,hashtable的确是检索速度很快,直接实现IDictionary接口,应该是可以的,但本人现在项目很紧,也没时间去验证了。等有时间,我也得好好去研究一下!
  回复  引用  查看    

#26楼  2006-01-25 08:04 狂人      
IList接口是有序的,也就是说,是按照添加入的顺序保存的

现在在一般情况下,我都是用List<T,T>泛型来做这样的事情
  回复  引用  查看    

#27楼  2006-06-28 00:11 Eunge      
建议看看数据结构中的“哈希”以及了解一下什么是“哈希冲突”,哈希就是哈希,和列表和本质区别。
  回复  引用  查看    

我疯掉了 这是什么语言编写得程序啊 Java?

不要告诉我是用java程序 如果是得化 请教用的什么编译器..........
  回复  引用    

#29楼 [楼主] 2006-07-25 11:26 叶漂      
@QQ254875073
c#
  回复  引用  查看    

#30楼  2006-10-30 05:49 UK [未注册用户]
http://www.codeproject.com/csharp/KeyedList.asp
  回复  引用    

#31楼  2006-11-02 11:13 qiucd [未注册用户]
不错。
  回复  引用    

#32楼  2006-11-22 19:54 zsuswy [未注册用户]
我也来凑个热闹
  回复  引用    

#33楼  2007-02-06 23:53 sddn [未注册用户]
用hashtable了,为什么还要排序?要排序为什么用hashtable?
  回复  引用    

#34楼  2007-02-09 10:51 piggybank [未注册用户]
刚入行的时候,CTO(比我大三岁的一个女孩)常说一句话:
>有时候程序员和程序员之间的差异,比人和猴子之间的差异还大。

呵呵,看各种 blog 的回复就知道了。

即想保留add时的原始顺序,又想检索速度快,用 SortedList——一种折中手段
至于.NET Framework 提供的各种数据结构之间的差异,不妨从它们对 ICollection,IList,IDictionary 接口的实现情况来理解:
符合 ICollection 的数据结构,必定有一定的顺序(因为可能你自己实现的类会有所变化),往往是保留了 Add 的顺序(例如Qeue和Stack)
IList 的特点在于有数字下标的索引(数组显然属于此列),显然定义上包含了ICollection
IDictionary 的特点在于用 key 索引,比 IList 更进一步

ok,以上几种接口定义下,就有了各种各样的变化——有ICollection的基本定义,就能够 for each,有IList,就能够用数字下标访问,有IDictionary,就能够用key检索

至于hashtable如何检索,我记得大学数据结构中不是讲过最简单的hashtable和哈夫曼编码等等么?找出来看看吧(人老了,我怕讲不清楚,哈哈)。

至于类型化的问题,.Net 2.0 有 SortedList<>和IDictionary<>

最后,建议大部分程序员朋友认真看看微软的 QuickStart,HowTo部分专门介绍了这些知识。
其实只要重视基础和细节,基础知识扎实一些,看ClassLibrary和API手册的时候认真扣抠字眼,自己就能弄明白了。

  回复  引用    

#35楼  2007-05-27 15:46 RyaN [未注册用户]
类似Java的LinkedHashMap,在里面维护一个链表结构
  回复  引用    

#36楼  2007-06-15 14:01 Robot·H      
ArrayList akeys=new ArrayList(ht.Keys); System.Collections
akeys.Sort(); //按字母顺序进行排序
foreach(string skey in akeys)
{
Console.Write(skey + ":");
Console.WriteLine(ht[skey]);//排序后输出
}
  回复  引用  查看    

我也遇到这样的问题,我要动态加载类,而类的处理有一定的顺序,hashtable不按我的意志来,帮我该变了,真是郁闷.现在还不知道如何处理,请高手指点.
  回复  引用    

#38楼  2007-09-03 17:47 kankan [未注册用户]
说的很对
  回复  引用    

#39楼  2008-05-04 21:47 liubo      
姐姐好。
  回复  引用  查看    

#40楼  2008-08-06 11:18 Donne.Y [未注册用户]
依照该方法测试结果也不对,我有如下表两个字段(colname|coltype):
colname|coltype
cpf01|272
cpf02|16
cpf10|16
cpf29|13
cpf37|16
cpf44|16
cpftype|0
cardtypeid|0
cpfacti|13
cpf14|0
cpf15|0
cpf16|0
cpf35|7
cpf69|7
cpfdate|7

用该方法:
[code]
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
sd.Add(ds.Tables[0].Rows[i]["colname"].ToString(), ds.Tables[0].Rows[i]["coltype"].ToString());
nsht.Add(ds.Tables[0].Rows[i]["colname"].ToString(), ds.Tables[0].Rows[i]["coltype"].ToString());
}

IDictionaryEnumerator ide = nsht.GetEnumerator();

while (ide.MoveNext())
{
Console.WriteLine(ide.Key);
}
[/code]
得到的结果确是这样:
CPF02,
CARDTYPEID
CPF15
CPF14
CPF44
CPF16
CPF10
CPF29
CPFDATE
CPF69
CPFACTI
CPF35
CPF37
CPF01
CPFTYPE
  回复  引用    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-01-05 11:58 编辑过


相关链接: