云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > Hashmap与Hashtable的选择

Hashmap与Hashtable的选择

  • 62 次阅读
  • 3 次下载
  • 2025/6/9 19:48:05

Hashmap与Hashtable的选择

(2009-12-13 17:05:08) 标

: 分类: 计算机-开发-JAVA

hashmap hashtable

1.问题

Hashtable和Hashmap是我们在开发过程中经常用来映射key到value的容器,在这两者之间选择使用的时候,我们经常被有经验者建议用 Hashmap,但我们可能对其中的缘由不甚了解。本文通过对原代码的一些简单分析,来解释原理,从而在使用中能够更好地做出选择。 2.分析

Hashtable和Hashmap实现的功能基本相同,但主要有3点区别。

2.1

第一个不同之处在于它们的继承关系有所不同。 public class Hashtable extends Dictionary public class HashMap extends AbstractMap

由上面的代码可以看出Hashtable是基于陈旧的Dictionary类的。在Java 1.2引入Map借口后,Hashtable也改进为可以实现 Map。HashMap是Map接口的一个实现,继承于较新的AbstractMap类。 Hashmap可以算作是Hashtable的升级版本,整体上Hashmap对Hashtable类优化了代码。比如说, 消除了hardcoding,增加了code reuse等等。当然这点不同,并不会对我们选择使用哪个产生影响。

2.2

第二个不同,在Hashmap中,null可以作为key,这样的key只有一个,可以有一个或多个key所对应的value为null。而在 Hashtable中,null不可以作为key,也不可以作为value。否则会抛出java.lang.NullPointerException。 Hashtable的put方法的源代码如下:

public synchronized Object put(Object key, Object 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 = key.hashCode();

int index = (hash & 0x7FFFFFFF) % tab.length;

for (Entry e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { Object old = e.value; e.value = value; return old; } }

}

从这段代码可以看出,在调用Hashtable的put方法时,首先会对put的value是否为空进行判断,如果为空,则会抛出NullPointerException,处理终止。如果对Hashtable中put一个null的key,代码在执行到

int hash = key.hashCode(); 的时候,因为key对象为空,同样会抛出NullPointerException,处理终止。 所以在编码时,诸如

hashtable.put(\为null 或者

hashtable.put(null, \为null 都是错误的。

当然,平时在编码时,put的key或者value不会那么明显就是个直接的字符串或者其他对象类型。它们可能是从DB或DTO中取得的或者通过一些计算 或转化得到的。这个时候要注意put的key或value是否有可能为null,如果有null的可能性,应该先进行判断并处理。以避免异常的产生。

看看下面这段错误代码。TABLEWORK是个hashtable WorkData wd = null;

wd = rs.getString(\から品番を取得する TABLEWORK.put(tableName, wd); // テーブルにセットする

wd对象是从数据库取得的,有可能会为空。所以在向Hashtable中put的时候,要对wd对象是否为空进行判断并对wd对象为空的情况进行处理。 修改后的代码如下。 WorkData wd = null;

wd = rs.getString(\から品番を取得する if (wd == null) {

// 存在しなければ、新規作成 wd = ComUtils.crtHinaban(); }

// テーブルにセットする

TABLEWORK.put(tableName, wd);

接下来看看Hashmap的put方法是如何对null处理的。 public Object put(Object key, Object value) { Object k = maskNull(key); int hash = hash(k);

int i = indexFor(hash, table.length);

for (Entry e = table[i]; e != null; e = e.next) { if (e.hash == hash && eq(k, e.key)) { Object oldValue = e.value; e.value = value;

e.recordAccess(this); return oldValue; } }

modCount++;

addEntry(hash, k, value, i); return null; }

在put方法的开始,没有像Hashtable那样对value为空进行判断并抛出异常。另外Object k = maskNull(key); 这句代码中的maskNull方法也对put的key进行如下处理。 static final Object NULL_KEY = new Object();

static Object maskNull(Object key) { return (key == null ? NULL_KEY : key); }

由此可以看出,在Hashmap put的时候,maskNull()方法会对put的值是否为空进行判断,如果为空,会产生一个新的对象(Object NULL_KEY = new Object();)即NULL_KEY。 另外还要注意一个问题,因为Hashmap可以存入null。所以当get()方法返回null值时,既可以表示 Hashmap中没有该key,也可以表示该key所对应的value为null。因此,在Hashmap中不能由get()方法来判断Hashmap中 是否存在某个key, 而应该用containsKey()方法来判断。

看下面这段代码

public static void main(String[] args) { Map map = new HashMap(); map.put(\

System.out.println(map.get(\ System.out.println(map.get(\

System.out.println(map.containsKey(\ System.out.println(map.containsKey(\ }

输出结果 null null true false

从上面这段试验代码的输出结果可以看出,如果通过get方法是无法判断key值1,2是否存在的,因为它们的返回的值都是null。正确的做法应该使用containsKey()方法来判断,从输出结果看,前者为true,后者为false。

2.3

第三个不同是Hashtable的方法是同步的,而Hashmap方法不是。Hashtable是synchronized,你可以不用采取任何特殊的行 为就可以在一个多线程的 应用程序中用一个Hashtable,而Hashmap的读写是unsynchronized, 在多线程的环境中要注意使用。这两者的不同是通过在读写方法上加synchronized关键字来实现的.有兴趣的话,大家可以看下Hashtable的 源代码,在需要线程安全的方法前都加上了synchronized关键字。下面举了

最常用的几个方法的定义。 hashtable

public synchronized Object get(Object key)

public synchronized Object put(Object key, Object value) public synchronized Object remove(Object key) public synchronized void clear()

从Hashmap的源代码可以看出没有这个关键字 hashMap

public V put(K key, V value) public V get(Object key)

有人可能会问, 既然能synchronized,能线程安全好啊。为什么不要呢,这里其实还是一个效率的问题。对于线程安全的方法,系统要进行加锁,减锁操作。性能会有 很大的影响。由于很多程序是在单线程或者说是线程安全的情况下工作的, 所以用synchronized就显得有些多余了。

当既要同步又要可以让null作为键或者值的时候,一个简便的方法就是利用Collections类的静态的 synchronizedMap()方法, Map synMap = Collections.synchronizedMap(map);

它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。

3. 总结

通过上述的内容,我们了解了Hashmap和Hashtable的几个主要的不同点。

Hashmap可以使用null作为key和value,而Hashtable不行。Hashtable是同步的,Hashmap是异步的。但是,因为在 需要时,Hashmap可以利用Collections类的静态的 synchronizedMap()方法来实现同步,其次Hashmap的功 能比Hashtable的功能更多,而且它不是基于一个陈旧的类的,所以才有人认为,在各种情况下,Hashmap都优先于Hashtable。 HashMap 是Hashtable 的轻量级实现(非线程安全的实现),他们都完成了Map 接口,主要

区别在于HashMap 允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap 允许将null 作为一个entry 的key 或者value,而Hashtable 不允许。 HashMap 把Hashtable 的contains 方法去掉了,改成containsvalue 和containsKey。因为contains

方法容易让人引起误解。

Hashtable 继承自Dictionary 类,而HashMap 是Java1.2 引进的Map interface 的一个实现。

最大的不同是,Hashtable 的方法是Synchronize 的,而HashMap 不是,在多个线程访问

Hashtable 时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable 和HashMap 采用的hash/rehash 算法都大概一样,所以性能不会有很大的差异。

搜索更多关于: Hashmap与Hashtable的选择 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

Hashmap与Hashtable的选择 (2009-12-13 17:05:08) 标签: 分类: 计算机-开发-JAVA hashmap hashtable 1.问题 Hashtable和Hashmap是我们在开发过程中经常用来映射key到value的容器,在这两者之间选择使用的时候,我们经常被有经验者建议用 Hashmap,但我们可能对其中的缘由不甚了解。本文通过对原代码的一些简单分析,来解释原理,从而在使用中能够更好地做出选择。 2.分析 Hashtable和Hashmap实现的功能基本相同,但主要有3点区别。 2.1 第一个不同之处在于它们的继承关系有所不同。 public class Hashtable extends D

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com