java集合框架12——HashMap和HashTable的区别

前面已经学习了Map的部分内容,主要是HashMap和HashTable,这一节我们来看看它们两有啥异同点。

1. HashMap和HashTable的相同点

HashMap和HashTable都是存储“键值对”的散列表,而且都是采用拉链法来实现的。存储的思想都是:通过table数组存储,数组的每个元素都是一个Entry,而一个Entry就是一个单项链表,Entry链表中的每个节点都保存了key-value数据。

HashMap和HashTable的相同点基本没啥好研究的,我们更多的是关注它们的不同点,

2. HashMap和HashTable的不同点

分析不同点时,我们也部分结合前面分析的源码,这样更加直观。

1)继承方式不同

HashMap继承与AbstractMap,实现了Map、Cloneable和java.io.Serializable接口。

HashTable继承与Dictionary,实现了Map、Cloneable和java.io.Serializable接口。

Dictionary是一个抽象类,它直接继承与Object类,没有实现任何接口。Dictionary是JDK1.0引入的,虽然也支持添加键值对,获取value等基本操作,但是它的API比Map少,而且Dictionary议案是通过Enumeration去遍历,Map则是通过Iterator去遍历。然而由于HashTable也实现了Map接口,所以它也支持Iterator遍历,这点后面再阐述。

2)线程安全不同

HashMap的方法是非同步的,若要在多线程下使用HashMap,需要我们额外的进行同步处理。对HashMap处理可以使用Collections类提供的synchronizedMap静态方法,或者直接使用JDK5.0之后提供的java.util.concurrent包里的ConcurrentHashMap类。

HashTable几乎所有方法都是同步的,前面都加了synchronized关键字,它支持多线程。

3)对null值的处理不同

HashMap的key和value都可以为null。

HashTable的key和value都不可以为null。

我们可以结合两者添加key-value的方法来看:

//HashMap中添加key-value的源码
public V put(K key, V value) {
	if (table == EMPTY_TABLE) { //如果哈希表没有初始化(table为空)
		inflateTable(threshold); //用构造时的阈值(其实就是初始容量)扩展table
	}
	//如果key==null,就将value加到table[0]的位置
	//该位置永远只有一个value,新传进来的value会覆盖旧的value
	if (key == null)
		return putForNullKey(value);

	int hash = hash(key); //根据键值计算hash值

	int i = indexFor(hash, table.length); //搜索指定hash在table中的索引

	//循环遍历Entry数组,若该key对应的键值对已经存在,则用新的value取代旧的value
	for (Entry<K,V> e = table[i]; e != null; e = e.next) {
		Object k;
		if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
			V oldValue = e.value;
			e.value = value;
			e.recordAccess(this);
			return oldValue; //并返回旧的value
		}
	}

	modCount++;
	//如果在table[i]中没找到对应的key,那么就直接在该位置的链表中添加此Entry
	addEntry(hash, key, value, i);
	return null;
}

//HashTable中添加key-value的源码
public synchronized V put(K key, V value) {
    //确保value不为空
    if (value == null) {
        throw new NullPointerException();
    }

    Entry tab[] = table;
    int hash = hash(key); //计算哈希值,如果key为null会抛出异常
    int index = (hash & 0x7FFFFFFF) % tab.length; //根据哈希值计算在数组中的索引
    for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) { //如果对应的key已经存在
            V old = e.value;
            e.value = value; //替换掉原来的value
            return old;
        }
    }
    //否则新添加一个Entry
    modCount++;
    if (count >= threshold) { //判断数组中的Entry数量是否已经达到阈值
        rehash(); //如果达到了,扩容

        tab = table;
        hash = hash(key); //重新计算哈希值
        index = (hash & 0x7FFFFFFF) % tab.length; //重新计算在新的数组中的索引
    }

    //创建一个新的Entry
    Entry<K,V> e = tab[index];
    //存到对应的位置,并将其next置为原来该位置的Entry,这样就与原来的连上了
    tab[index] = new Entry<>(hash, key, value, e);
    count++;
    return null;
}

从上面的代码中可以看出,HashTable的key和value都不能为null,否则会抛出异常,异常是NullPointerException。HashMap的key和value都可以为null,当key为null时,HashMap会将其固定的插入table[0]位置,而且table[0]的位置只会容纳一个key为null的值。

4)支持的遍历种类不同

HashMap只支持Iterator遍历。

HashTable支持Iterator和Enumeration两种方式遍历。

5)初始容量和扩容方式不同

HashMap的默认容量是16,,扩容时,每次将容量变为原来的2倍;

HashTable的默认容量是11,扩容时,每次将容量变为原来的2倍+1。

6)添加key-value的hash值算法不同

HashMap添加元素时,是使用自定义的哈希算法;

HashTable是直接采用key的hashCode()。我们看一下源码:

static int hash(int h) {
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

// HashMap的添加
public V put(K key, V value) {
    //省略代码……
    int hash = hash(key.hashCode());
    // 省略代码……
}

//HashTable的添加
public synchronized V put(K key, V value) {
    //省略代码……
    int hash = key.hashCode();
    //省略代码……
}

7)部分API不同

HashMap不支持contains(Object value)方法,没有重写toString()方法;

HashTable支持contains(Object value)方法,而且重写了toString()方法。

以上就是两者的主要区别,如有补充的或者错误之处,欢迎留言指正~

_____________________________________________________________________________________________________________________________________________________

-----乐于分享,共同进步!

-----更多文章请看:http://blog.csdn.net/eson_15

时间: 2024-11-01 11:36:51

java集合框架12——HashMap和HashTable的区别的相关文章

Java 集合系列 11 hashmap 和 hashtable 的区别

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 Java 集合系列 05 Vector详细介绍(源码解析)和使用示例 Java 集合系列 06 Stack详细介绍(源码解析)和使用示例 Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和

Java集合框架之HashMap

HashMap 的底层由一个散列表来实现,存储的内容是键值对(key-value),且键值不能重复,最多允许有一个null值. 1.Map与Set的关系 Set集合的特点是不能存储重复元素,不能保持元素插入时的顺序,且key值最多允许有一个null值. 由于Map中的key与Set集合特点相同,所以如果将Map中的value值当作key的附属的话,所有的key值就可以组成一个Set集合. 两者的实现类图也比较相似,见Java集合框架之基础. 2.Map接口中定义的方法 Map接口中定义的部分重要

java集合框架08——HashMap和源码分析

本文为博主原创文章,转载请注明出处:http://blog.csdn.net/eson_15/article/details/51154989 上一章总体分析了Map架构,并简单分析了一下AbstractMap源码,这一章开始我们将对Map的具体实现类进行详细的学习.本章先研究HashMap.依然遵循以下步骤:先对HashMap有个整体的认识,然后学习它的源码,深入剖析HashMap. 1.HashMap简介 首先看一下HashMap的继承关系 java.lang.Object ? java.u

Java中HashSet,HashMap和HashTable的区别(转)

HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的是HashMap进行实现的,但是没有key-value,只有HashMap的key set的视图,HashSet不容许重复的对象 2:Hashtable是基于Dictionary类的,而HashMap是基于Map接口的一个实现 3:Hashtable里默认的方法是同步的,而HashMap则是非同步的

java集合框架中Set和List的区别

1. Set 接口实例存储的是无序的,不重复的数据.List 接口实例存储的是有序的,可以重复的元素. 2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>. 3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度.查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> . 原文地址:https://www.cnb

Java 集合系列 12 TreeMap

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 Java 集合系列 05 Vector详细介绍(源码解析)和使用示例 Java 集合系列 06 Stack详细介绍(源码解析)和使用示例 Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和

java集合框架之java HashMap代码解析

 java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/article/java-hashmap-java-collection.html 签名(signature) public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Se

java集合框架小结(进阶版)之HashMap篇

基本概念: Hash(哈希):hash一般也译作“散列”.事实上,就是一个函数,用于直接定址.将数据元素的关键字key作为变量,通过哈希函数,计算生成该元素的存储地址. 冲突:函数是可以多对一的.即:多个自变量可以映射到同一函数值.一般而言,不同的key的hash值是不同的.在往hash表中映射的时候,不同的hash值可能映射到同一存储地址,这种情况被称为冲突. 解决冲突的方法: 1. 链表法:将冲突的各个元素用一个一维数组来维护.(java源码实现) 2. 开发寻址法:具体的有线性探测法.二次

浅谈JAVA集合框架(转载)_常用的Vector和HashMap

原作者滴着:http://www.cnblogs.com/eflylab/archive/2007/01/20/625237.html Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection classes).集合在java中非常重要,在讨论之前,先来看几个面试中的经典问题. 1 Collection 和 Collections的区别. 2 List, Set, Map是否继承自