C#中的HashTable怎么遍历取值

C#中的HashTable怎么遍历取值,第1张

foreach( DictionaryEntry de in hashTable)

{

consoleWriteLine("Key -- {0}; Value --{1}", deKey, deValue);

}

第一个区别就先来说说继承关系吧

如果你baidu一下,会发现网上的大致说法与“由于Java发展的历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 12引进的Map接口的一个实现。”相同。

这种说法没有错,但是不够准确,特别是对于我们这种大众菜鸟来说,如果不去深究的话,可能就会造成一些理解上的差异。简单的认为Hashtable没有继承Map接口。

我们可以参考一下最新的JDK16的源码,看看这两个类的定义:

public class Hashtable<K,V>extends Dictionary<K,V> implements Map<K,V>, Cloneable, javaioSerializable {…}public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {…}

可以看到hashtable也是继承了Map接口。

它们的不同是Hashtable(since JDK10)就继承了Dictionary这个抽象类,

HashMap(since JDK12)继承的则是AbstractMap这个抽象类。

第二个区别我们从同步和并发性上来说说它们两个的不同。

可以通过这两个类得源码来分析,Hashtable中的主要方法都做了同步处理,而HashMap则没有。

可以说Hashtable在默认情况支持同步,而HashMap在默认情况下是不支持的。

我们在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

对HashMap的同步处理可以使用Collections类提供的synchronizedMap静态方法;

或者直接使用JDK50之后提供的javautilconcurrent包里的ConcurrentHashMap类。

第三个区别就是它们对于null值的处理方式了。

我们依然能够从源代码中得知,Hashtable中,key和value都不允许出现null值。

public synchronized V put(K key, V value) {

// Make sure the value is not null

if (value == null) {

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable

Entry tab[] = table;

int hash =

keyhashCode();

int index = (hash & 0x7FFFFFFF) % tablength;

//…

}

在我们使用上面的方法时,

如参数value为null,可以从代码中直接看出程序会抛出NullPointerException;

而在key为null时,则会在“int hash =

keyhashCode();“这段计算Hash值的过程中抛出NullPointerException。

而在在HashMap中,允许null作为key存在,并且和其他key的特性一样,这样的null值key只能有一个;

另外HashMap允许多个value为null。

这样大家就要注意了, HashMap中就不能用get(key)方法来判断HashMap中是否存在某个key,因为value为null和不存在该key的Entry都会返回null值,而应该用containsKey()方法来判断了。

import

javautilHashMap;

import javautilMap;

import

javautilMapEntry;

public class TestCase

{

 

public static void main(String[] args) {

Map<Integer,String>

hashMap = new HashMap<Integer,String>();

hashMapput(0, null);

hashMapput(1,

"one");

hashMapput(2,

"two");

hashMapput(null,

"null");

for(Entry<Integer,

String> e : hashMapentrySet()) {

Systemoutprintln("Key:

" + egetKey() + " -- Value: " + egetValue());

}

Systemoutprintln(hashMapget(0));

Systemoutprintln(hashMapget(4));

Systemoutprintln("Contains

key 0  :" + hashMapcontainsKey(0));

Systemoutprintln("Contains

key 4  :" + hashMapcontainsKey(4));

Systemoutprintln("Contains

value null  :" + hashMapcontainsValue(null));

}

}

结果:

Key: null -- Value:

null

Key: 0 -- Value: null

Key: 1 -- Value: one

Key: 2 -- Value: two

null

null

Contains key 0  :true

Contains key 4 

:false

Contains value null 

:true

第四个不同就是它们两个Hash值的获取方式了。

还是通过源代码源代码,Hashtable是直接使用key对象的hash值。

public synchronized V put(K key, V value) {

// Make sure the value is not null 

if (value == null) {

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable

Entry tab[] = table;

int hash = keyhashCode();//hashcode

int index = (hash & 0x7FFFFFFF) % tablength;

//…

}

而HashMap则是利用key对象的hash值重新计算一个新的hash值。 

 

public V put(K key, V value) {

if (key == null)

return putForNullKey(value);

 

int hash= hash(keyhashCode());//hashcode

int i = indexFor(hash, tablelength);

//…

}

 

static int hash(int h)

{

h ^=(h >>> 20) ^ (h >>> 12);

returnh ^ (h >>> 7) ^ (h >>> 4);

}

第五个不同就是Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。

HashMap中内部数组的初始容量是16, 加载因子为075,而且数组容量增容后也要是2指数次幂:

/

 The default

initial capacity - MUST be a power of two

/

static final int

DEFAULT_INITIAL_CAPACITY = 16;

 

/

 The load factor

used when none specified in constructor

/

static final float

DEFAULT_LOAD_FACTOR = 075f;

HashTable中的内部数组的初始容量是11,加载因子也是075数组的增容方式为(oldCapacity 2 + 1):

public Hashtable() {

this(11,

075f);

}

 

protected void

rehash() {

int

oldCapacity = tablelength;

Entry[]

oldMap = table;

int

newCapacity = oldCapacity  2 + 1;

//…

}

第六个不同我们从它们两个遍历方式的内部实现上来说。

Hashtable HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

第七个不同时它们的拷贝构造函数的不同。

依然是通过查看源码,可以发现它们两个对于拷贝函数初始容量的不同值。

HashMap的实现是:

public

HashMap(Map< extends K,  extends V> m) {

this(Mathmax((int)

(msize() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);

putAllForCreate(m);

}

而Hashtable的实现是:

public

Hashtable(Map< extends K,  extends V> t) {

this(Mathmax(2tsize(),

11), 075f);

putAll(t);

}

一 简介

名词介绍 散列表(Hash table 也叫哈希表) 是根据关键码值(Key value)而直接进行访问的数据结构 也就是说 它通过把关键码值映射到表中一个位置来访问记录 以加快查找的速度 这个映射函数叫做散列函数 存放记录的数组叫做散列表

HashTable 表的优点 HashTable是System Collections命名空间提供的一个容器 HashTable中的key/value均为object类型 所以HashTable可以支持任何类型的key/value键/值对

HashTable的优点就在于其索引的方式 速度非常快

二 哈希表的简单 *** 作

在哈希表中添加一个keyvalue键值对 HashtableObject Add(key value);

在哈希表中去除某个keyvalue键值对 HashtableObject Remove(key);

从哈希表中移除所有元素 HashtableObject Clear();

判断哈希表是否包含特定键key HashtableObject Contains(key);

下面控制台程序将包含以上所有 *** 作

using System;

using System Collections;       //file使用Hashtable时 必须引入这个命名空间

class hashtable

{

public static void Main()

{

Hashtable ht=new Hashtable();  //file创建一个Hashtable实例

ht Add(E e);                   //添加keyvalue键值对

ht Add(A a);

ht Add(C c);

ht Add(B b);

string s=(string)ht[A];

if(ht Contains(E))             //file判断哈希表是否包含特定键 其返回值为true或false

Console WriteLine(the E keyexist);

ht Remove(C);                 //移除一个keyvalue键值对

Console WriteLine(ht[A]);     //此处输出a

ht Clear();                   //移除所有元素

Console WriteLine(ht[A]);     //file此处将不会有任何输出

}

}

遍历哈希表

遍历哈希表需要用到DictionaryEntry Object 代码如下

for(DictionaryEntry de in ht) // fileht为一个Hashtable实例

{

Console WriteLine(de Key);   //de Key对应于keyvalue键值对key

Console WriteLine(de Value); //de Key对应于keyvalue键值对value

}

四 对哈希表进行排序

对哈希表进行排序在这里的定义是对keyvalue键值对中的key按一定规则重新排列 但是实际上这个定义是不能实现的 因为我们无法直接在Hashtable进行对key进行重新排列 如果需要Hashtable提供某种规则的输出 可以采用一种变通的做法

ArrayList akeys=new ArrayList(ht Keys);  // file别忘了导入System Collections

akeys Sort();                           // file按字母顺序进行排序

for(string skey in akeys)

{

Console Write(skey + );

Console WriteLine(ht[skey]);            // 排序后输出

lishixinzhi/Article/program/net/201311/12422

HashTable在SystemCollections的命名空间下。

是个根据object索引键访问object值的集合。

没有泛型,使用的时候只能进行强制转换。

Dictionary只能通过string类来定义键值,

如Dictionary d;d["wang"]="王";

CollectionBase只能通过数字索引来访问,

如CollectionBase col;col[0]="好";

HashTable比起上述两种类型来说有更强的访问能力。如:

HastTable hs=new HashTable();

hs["wang"]="王";

hs[0]="好";

然而上述两个集合类有泛型类的实现Dictionary<>和List<>,可以实现强类型化。(返回的是自己定制的类型)

HashTable没有泛型类,返回的都是object类型。使用的时候必须进行强制转化。

Hashtable 类基于 IDictionary 接口,因此该集合中的每一元素是键和值对。

Hashtable 由包含集合元素的存储桶组成。存储桶是 Hashtable 中各元素的虚拟子组,与大多数集合中进行的搜索和检索相比,它可令搜索和检索更简单、更快速。每一存储桶都与一个哈希代码关联,该哈希代码是使用哈希函数生成的并基于该元素的键。

哈希函数是基于键返回数值哈希代码的算法。键是正被存储的对象的某一属性的值。哈希函数必须始终为相同的键返回相同的哈希代码。一个哈希函数能够为两个不同的键生成相同的哈希代码,但从哈希表检索元素时,为每一唯一键生成唯一哈希代码的哈希函数将令性能更佳。

在 Hashtable 中用作元素的每一对象必须能够使用 ObjectGetHashCode 方法的实现为其自身生成哈希代码。但是,还可以通过使用 Hashtable 构造函数(该构造函数将 IHashCodeProvider 实现作为其参数之一接受),为 Hashtable 中的所有元素指定一个哈希函数。

在将一个对象添加到 Hashtable 时,它被存储在存储桶中,该存储桶与匹配该对象的哈希代码的哈希代码关联。当在 Hashtable 内搜索一个值时,为该值生成哈希代码,并且搜索与该哈希代码关联的存储桶。

例如,一个字符串的哈希函数可以采用该字符串中每一字符的 ASCII 代码并它们添加到一起来生成一个哈希代码。字符串“picnic”将具有与字符串“basket”的哈希代码不同的哈希代码;因此,字符串“picnic”和“basket”将处于不同的存储桶中。与之相比,“stressed”和“desserts”将具有相同的哈希代码并将处于相同的存储桶中。

using System;

using SystemCollections;

public class SamplesHashtable

{

public static void Main()

{

// Creates and initializes a new Hashtable

Hashtable myHT = new Hashtable();

myHTAdd( "First ", "3 ");

myHTAdd( "Second ", "2 ");

myHTAdd( "Third ", "1 ");

// Displays the properties and values of the Hashtable

ConsoleWriteLine( "myHT " );

ConsoleWriteLine( " Count: {0} ", myHTCount );

ConsoleWriteLine(myHT[ "First "]);//也可以这它!

ConsoleWriteLine( " Keys and Values: " );

PrintKeysAndValues( myHT );

}

public static void PrintKeysAndValues( Hashtable myList )

{

IDictionaryEnumerator myEnumerator = myListGetEnumerator();

ConsoleWriteLine( "\t-KEY-\t-VALUE- " );

while ( myEnumeratorMoveNext() )

ConsoleWriteLine( "\t{0}:\t{1} ", myEnumeratorKey, myEnumeratorValue);

}

}

以上就是关于C#中的HashTable怎么遍历取值全部的内容,包括:C#中的HashTable怎么遍历取值、2.hash map和hash-table的区别、C#中HashTable简介和使用用法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9287463.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存