Hashtable和HashMap源码分析
JDK中自带的Hashtable和HashMap是数据结构中哈希表的实现。除了这两个,还有一个HashSet的实现,但是HashSet基本是基于HashMap实现的,因此在这里我们只讨论Hashtable和HashMap的实现细节。
首先列出经过源码分析,得出的关于Hashtable和HashMap之间的异同点如下:
1、Hashtable和HashMap的继承关系比较如下:
其中没有列出它们两个继承的Cloneable和Serializable接口,在下面的分析也是一样,不会分析比较它们的序列化和Cloneable的实现。
2、Hashtable和HashMap之间最为明显的区别:同步处理
在Hashtable的实现中,所有的外部访问方法都进行了同步化处理,即在方法中添加synchronized关键字;
Hashtable中的方法示例:
- public synchronized V put(K key, V value) {
- //此处省略内部实现
- }
- public synchronized V remove(Object key) {
- //此处省略内部实现
- }
而在HashMap的实现中,没有进行同步化处理;
HashMap中的同样两个方法示例:
- public V put(K key, V value) {
- //此处省略内部实现
- }
- public V remove(Object key) {
- //此处省略内部实现
- }
3、Hashtable和HashMap关于输入的key和value的限制:
在Hashtable的实现中,不允许添加key或是value为null的键值对,如果key为null,则在put(K key,V value)方法调用hash()方法获取hash值时会抛出空指针异常, 而如果value为null,则在刚进入put(K key, V value)是就会检查而抛出空指针异常,如下具体程序所示:
如下所示为Hashtable中的实现:
- public synchronized V put(K key, V value) {
- // Make sure the value is not null
- if (value == null) {//在这里对value值进行了检验,如果为null,则抛出空指针异常
- throw new NullPointerException();
- }
- // Makes sure the key is not already in the hashtable.
- Entry tab[] = table;
- int hash = hash(key);//在这里调用了下面的hash(Object k)方法
- //在此省略了下面的实现......
- }
- //在下面的方法中可以看出,只要传入的k值为null,则在下面调用时就会产生空指针异常
- private int hash(Object k) {
- if (useAltHashing) {
- if (k.getClass() == String.class) {
- return sun.misc.Hashing.stringHash32((String) k);
- } else {
- int h = hashSeed ^ k.hashCode();
- h ^= (h >>> 20) ^ (h >>> 12);
- return h ^ (h >>> 7) ^ (h >>> 4);
- }
- } else {
- return k.hashCode();
- }
- }
而在HashMap的实现中,指定索引位置0处用来存放key值为null的键值对,如果在put方法中传入key值为null,如果索引位置0处存在已经存储的元素,则使用现在传进来的value值替换原来的value值,如果没有存储元素,则直接放置。所以我们容易知道,在HashMap中,键值key为null的键值对只能在索引位置为0的地方存储一个,即在整个HashMap中只允许有一个键值对的key为null,后面添加的只是在修改value值。
如下所示为HashMap中的实现:
- public V put(K key, V value) {
- if (key == null)
- return putForNullKey(value);
- //在这里省略了后面key不为null的实现
- }
- //当key为null时调用
- private V putForNullKey(V value) {
- for (Entry<K,V> e = table[0]; e != null; e = e.next) {
- //此时索引位置0处不为null,则替换原来的value值
- if (e.key == null) {
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- //索引位置0处为空,则将键值对放置进去
- addEntry(0, null, value, 0);
- return null;
- }
4、在Hashtable和HashMap中,在每一次添加元素时,都会检查此时表中已有的数据个数与临界值的大小关系,当已存入的数据个数大于等于threshold临界值时,Hashtable会调用rehash()方法来对数组进行扩充,HashMap会调用resize(int capacity)方法来对数组进行扩充,然后依次遍历原数组,重新计算元素的hash值,存储到新的数组中,而且两者都是将数组扩大一倍,其中的临界值threshold = loadFactor(装载因子,默认0.75) * capacity(数组大小);
5、在Hashtable和HashMap中都提供了迭代器可让外部调用。在Hashtable和HashMap中均有entrySet()、keySet()、values()方法,分别返回Set<Entry<K,V>>、Set<K>、Collection<V>这三种类型的对象引用,其中就像上面说的,Hashtable返回的对象都是经过同步处理的,举个例子如下:
- public Set<Map.Entry<K,V>> entrySet() {
- if (entrySet==null)
- entrySet = Collections.synchronizedSet(new EntrySet(), this);
- return entrySet;
- }
而在HashMap中返回的对象引用,没有经过同步处理,举例如下:
- public Set<Map.Entry<K,V>> entrySet() {
- return entrySet0();
- }
- private Set<Map.Entry<K,V>> entrySet0() {
- Set<Map.Entry<K,V>> es = entrySet;
- return es != null ? es : (entrySet = new EntrySet());
- }
相关推荐
Java集合专题总结:HashMap和HashTable源码...本文总结了HashMap和HashTable的源码学习和面试总结,涵盖了它们的存储结构、构造方法、get和put方法的源码分析、Hash表的特点和缺点、HashTable和HashMap的区别等内容。
5. 源码分析: 查看`HashTable`和`HashMap`的源码,可以发现两者在内部实现上也有所不同。`HashTable`直接使用了数组+链表的方式,而`HashMap`在Java 8及以后版本引入了红黑树优化,当链表长度达到一定阈值(8)时...
在HashMap的源码中,插入、删除和查找操作都是围绕这些数据结构和变量展开的。插入操作会计算键的哈希值,根据哈希值找到对应的数组位置,并可能触发链表或红黑树的插入操作。删除操作同样依据哈希值找到节点,然后...
### HashMap源码分析 #### 一、概述 `HashMap`是Java编程语言中非常重要的一个数据结构,它属于`java.util`包的一部分,是`Map`接口的一个具体实现类。`HashMap`允许存储键值对,并且支持使用`null`作为键或值,这...
#### 二、HashMap线程安全问题分析 在多线程环境中,`HashMap`的主要线程安全问题包括但不限于: 1. **链表死循环问题**:在JDK 1.7中,当多个线程同时进行`put`操作时,可能会出现链表死循环的情况,这是一个严重...
- `null`值:`Hashtable`不允许`null`键和`null`值,而`HashMap`允许`null`键但不允许`null`值。 - 构造器默认容量:`Hashtable`默认容量为11,`HashMap`为16。 【总结】 `Hashtable`作为古老的容器,虽然在单线程...
10. **面试常见问题**:面试中常问的问题包括HashMap的扩容机制、哈希冲突解决策略、线程安全性、迭代器的使用等,还可能涉及HashMap的源码分析。 通过深入学习和理解HashMap,不仅可以提高代码的编写效率,也能在...
本文主要讲述了 Java 中的并发编程,包括 atomic 包的介绍、CAS 算法的原理、ABA 问题的解决方案,以及 collections 中的 HashMap、HashTable 和 ConcurrentHashMap 的源码分析。 Atomic 包的介绍 ----------------...
之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也是说HashSet里面有一个HashMap(适配器模式)。因此本文将重点分析HashMap。 HashMap实现了Map...
本文主要探讨了几个关键的集合接口和实现类的底层源码,包括List、HashMap、HashSet等,以及它们的基本操作。 首先,Collection接口是所有单值集合的父接口,提供了增加、删除、遍历元素的基本方法。例如,`add()`...
HashMap是Java编程语言中最常用的集合类之一,尤其在面试中,HashMap的相关知识是考察...这套学习资料应该包含了HashMap的实例分析、源码解读、常见面试题以及实战演练等内容,确保你全面掌握这一核心Java数据结构。
Java并发系列之ConcurrentHashMap源码分析 ConcurrentHashMap是Java中一个高性能的哈希表实现,它解决了HashTable的同步问题,允许多线程同时操作哈希表,从而提高性能。 1. ConcurrentHashMap的成员变量: ...
hashmap源码 to-be-architect to be a Java architect,you should learn these.This page is updated irregularly. Java基础 深入分析 Java SPI 机制和原理 并发编程专题 Executors线程池 线程池ThreadPoolExecutor...
本文将深入探讨HashMap的基本特性、哈希表数据结构以及JDK 1.7版本中的HashMap源码分析。 首先,HashMap的基本特性如下: 1. **允许null值**:HashMap允许键和值为null,而Hashtable则不允许。 2. **非线程安全**...
集合源码分析 JAVA: 基本语法 static 修饰变量 方法 静态块(初始化块 构造函数 ) 静态内部类() 静态导包 final() transient() foreach循环原理() volatile底层实现() equals和hashcode(, ) string,stringbuffer和...
与`HashMap`中的`Node`类似,但`Node`在JDK8中对`value`和`next`字段使用了`volatile`关键字,确保多线程环境下的可见性。`Node`不提供直接修改`value`的方法,而是通过`find`方法辅助`get`操作。 3. **扩容机制** ...
《Java技术指南》是一份面向Java程序员的综合技术文档,其涵盖了Java语言从基础到高级的多个方面,旨在帮助Java入门者和进阶者提升技能...文档通过丰富的实例和源码分析,为Java程序员提供了一个全面、深入的学习平台。
面试必考之HashMap源码分析与实现.mp4 │ │ │ ├─2.探索JVM底层奥秘ClassLoader源码分析与案例讲解 │ │ 2.探索JVM底层奥秘ClassLoader源码分析与案例讲解.wmv │ │ │ ├─3.锁、分布式锁、无锁实战全局性ID...