Hashtable源码分析

Hashtable简介

Hashtable简介
Hashtable声明
Hashtable基本数据结构
键值对/Entry
Hashtable方法分析
public synchronized boolean contains(Object value)
public synchronized boolean containsKey(Object key)
public synchronized V put(K key, V value)
private void addEntry(int hash, K key, V value, int index)
public synchronized V remove(Object key)
public synchronized Object clone()
protected void rehash()

Hashtable声明

public class Hashtable extends Dictionary implements Map, Cloneable, java.io.Serializable

Hashtable和HashMap一样也是散列表,存储元素也是键值对;

Hashtable继承于Dictionary类(Dictionary类声明了操作键值对的接口方法),实现Map接口(定义键值对接口);

Hashtable大部分类用synchronized修饰,证明Hashtable是线程安全的;

Hashtable基本数据结构

  • private transient Entry<?,?>[] table:键值对/Entry数组,每个Entry本质上是一个单向链表的表头
  • private int threshold:rehash阈值
  • private float loadFactor:装填因子
  • private transient int modCount = 0: Hashtable结构化修改次数,用来实现fail-fast机制;
  • private transient volatile Set<Map.Entry<K,V>> entrySet:Hastable视图,键值对集合;
  • private transient volatile Set<K> keySetHastable视图,key集,Hashtable中key不可重复;
  • private transient volatile Collection<V> valuesHastable视图,value集合,可重复;
    • Hashtable中key和value是一对多关系;

键值对/Entry

 1 private static class Entry<K,V> implements Map.Entry<K,V> {
 2     final int hash;
 3     final K key;
 4     V value;
 5     Entry<K, V> next;
 6     ...
 7     // 计算键值对的hashCode
 8     public int hashCode() {
 9         // "^" 按位异或, hash在调用构造器时传入
10         return hash ^ Objects.hashCode(value);
11     }
12 }

Hashtable方法分析

public synchronized boolean contains(Object value)

public boolean containsValue(Object value)内部调用contains(value);

判断是否含有该value的键值对,在Hashtable中hashCode相同的Entry用链表组织,hashCode不同的存储在Entry数组table中;

// in contains() method.
Entry<?,?> tab[] = table;
// 查找:遍历所有Entry链表
for (int i = tab.length ; i-- > 0 ;) {
    for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
        if (e.value.equals(value)) {
            return true;
        }
    }
}
return false;

public synchronized boolean containsKey(Object key)

根据key的hashCode计算对应entry在table中的index;

 1 Entry<?,?> tab[] = table;
 2 int hash = key.hashCode();
 3 /**
 4  * 计算index, % tab.length防止数组越界
 5  * index表示key对应entry所在链表表头
 6  */
 7 int index = (hash & 0x7FFFFFFF) % tab.length;
 8 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 9     if ((e.hash == hash) && e.key.equals(key)) {
10         return true;
11     }
12 }
13 return false;

public synchronized V get(Object key):根据指定key查找对应value,查找原理与containsKey相同,查找成功返回value,否则返回null;

public synchronized V put(K key, V value)

设置键值对,key和value都不可为null,设置顺序:

  1. 如果Hashtable含有key,设置(key, oldValue) -> (key, newValue);
  2. 如果Hashtable不含有key, 调用addEntry(...)添加新的键值对;
private void addEntry(int hash, K key, V value, int index)

当键值对个数超过阈值,先进行rehash然后添加entry,否则直接添加entry;

public synchronized V remove(Object key)

remove操作,计算key所在链表表头table[index],然后进行单向链表的节点删除操作

public synchronized Object clone()

对Hashtable的浅拷贝操作,浅拷贝所有bucket(单向链表组织形式)的表头;

protected void rehash()

当Hashtable中键值对总数超过阈值(容量*装载因子)后,内部自动调用rehash()增加容量,重新计算每个键值对的hashCode;

int newCapacity = (oldCapacity << 1) + 1计算新容量 = 2 * 旧容量 + 1;并且根据新容量更新阈值;

...
for (int i = oldCapacity ; i-- > 0 ;) {
    // 拷贝每个Entry链表
    for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
        Entry<K,V> e = old;
        old = old.next;
        // 重新计算每个Entry链表的表头索引(rehash)
        int index = (e.hash & 0x7FFFFFFF) % newCapacity;
        // 开辟链表节点
        e.next = (Entry<K,V>)newMap[index];
        // 拷贝
        newMap[index] = e;
    }
}
时间: 2024-10-14 00:33:33

Hashtable源码分析的相关文章

Java入门系列之集合Hashtable源码分析(十一)

前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hashtable源码分析 我们通过在控制台中实例化Hashtable并添加键值对实例代码来分析背后究竟做了哪些操作,如下: public static void main(String[] args) { Hashtable hashtable = new Hashtable(); hashtable.p

JAVA的HashTable源码分析

Hashtable简介 Hashtable同样是基于哈希表实现的,同样 每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中. Hashtable同样 实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆 . HashTable源码剖析 Hashtable的源码的很多实现都与HashMap差不多,源码如下(加入了比较详细的注

【Java源码分析】HashTable源码分析

类的定义 public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable {} 注意前面虽然说HashTable和HashMap是非常像的,但是这两个类的父类是不一样的.前者是字典类的子类,后者是抽象Map的子类. HashTable 也是将key映射到value的集合类,key不允许为null,并且作为key的类是必须实现h

Java集合之Hashtable源码分析

概述 Hashtable也是基于哈希表实现的, 与map相似, 不过Hashtable是线程安全的, Hashtable不允许 key或value为null. 成员变量 Hashtable的数据结构和HashMap一样, 采用 数组加链表的方式实现. 几个成员变量与HashMap一样: 方法 Hashtable的方法与HashMap基本一样, 只是 Hashtable方法加上了 synchronized 关键字, 保证Hashtable是线程安全的. 主要说说Hashtable与HashMap的

java集合框架09——HashTable和源码分析

上一章我们学习了HashMap的源码,这一节我们来讨论一下HashTable,HashTable和HashMap在某种程度上是类似的.我们依然遵循以下步骤:先对HashTable有个整体的认识,然后学习它的源码,深入剖析HashTable. 1.HashTable简介 首先看一下HashTable的继承关系 java.lang.Object ? java.util.Dictionary<K, V> ? java.util.Hashtable<K, V> public class H

史上最详细的HashTable源码解析,最容易懂

HashTable源码分析 更多资源和教程请关注公众号:非科班的科班.如果觉得我写的还可以请给个赞,谢谢大家,你的鼓励是我创作的动力###1.前言Hashtable 一个元老级的集合类,早在 JDK 1.0 就诞生了 ###1.1.摘要在集合系列的第一章,咱们了解到,Map 的实现类有 HashMap.LinkedHashMap.TreeMap.IdentityHashMap.WeakHashMap.HashTable.Properties 等等.###1.2.简介Hashtable 一个元老级

Hashtable、ConcurrentHashMap源码分析

Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角度分析一下两者的异同,首先给出二者的继承关系图. Hashtable类属性和方法源码分析 我们还是先给出一张Hashtable类的属性和方法图,其中Entry<K,V>是Hashtable类的静态内部类,该类继承自Map.Entry<K,V>接口.如下将会详细讲解Hashtable类中

[源码解析]HashMap和HashTable的区别(源码分析解读)

前言: 又是一个大好的周末, 可惜今天起来有点晚, 扒开HashMap和HashTable, 看看他们到底有什么区别吧. 先来一段比较拗口的定义: Hashtable 的实例有两个参数影响其性能:初始容量 和 加载因子.容量 是哈希表中桶 的数量,初始容量 就是哈希表创建时的容量.注意,哈希表的状态为 open:在发生“哈希冲突”的情况下,单个桶会存储多个条目,这些条目必须按顺序搜索.加载因子 是对哈希表在其容量自动增加之前可以达到多满的一个尺度.初始容量和加载因子这两个参数只是对该实现的提示.

HashMap与TreeMap源码分析

1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Java这么久,也写过一些小项目,也使用过TreeMap无数次,但到现在才明白它的实现原理).因此本着"不要重复造轮子"的思想,就用这篇博客来记录分析TreeMap源码的过程,也顺便瞅一瞅HashMap. 2. 继承结构 (1) 继承结构 下面是HashMap与TreeMap的继承结构: pu