记录了HashMap也来看看Hashtable吧,最近打算换份实习,所以想看看书回顾一下,不然就快记不得了.....囧啊囧啊,记性太差怎么破???

Hashtable里面的一些变量:

Entry<?,?>[] table : HashTable采用"拉链法"实现哈希表,每一个Entry代表了一个键值对(key-value)。

transient int count:hashtable里面键值对的个数;

private int threshold:hashtable的阀值(threshols = capacity * loadFactor);

float loadFactor:加载因子;

transient int modCount :hashtable被修改的次数,用来实现fast-fail机制。fast-fail机制就是在并发集合中,其进行迭代操作时,若有其他线程对其进行结构性的修改,这时迭代器会立马感知到,并且立即抛出              ConcurrentModificationException异常。

Hashtable的定义如下:

 public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
...
}

可以看出Hashtable实现了Map接口,同时继承了Dictionary类。Map接口是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。Dictionary 类是任何可将键映射到相应值的类(如 Hashtable)的抽象父类。每个键和每个值都是一个对象。在任何一个 Dictionary 对象中,每个键至多与一个值相关联。给定一个 Dictionary 和一个键,就可以查找所关联的元素。任何非 null 对象都可以用作键或值。

看看Hashtable常用的构造函数的实现:

默认的构造函数:容量为11,加载因子为0.75

 public Hashtable() {
this(11, 0.75f);
}

用指定的初始容量和默认的加载因子构造:

 public Hashtable(int initialCapacity) {
this(initialCapacity, 0.75f);
}

用指定的初始容量和指定的加载因子构造:

  public Hashtable(int initialCapacity, float loadFactor) {
// 参数合法性验证
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal Load: "+loadFactor); if (initialCapacity==0)
initialCapacity = 1;
this.loadFactor = loadFactor;
//用指定容量初始化table数组
table = new Entry<?,?>[initialCapacity];
//计算table的阀值
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}

再来看看Put方法和get方法:

  首先是put方法,put方法的整个处理流程是:计算key的hash值,根据hash值获得key在table数组中的索引位置,然后迭代该key处的Entry链表(我们暂且理解为链表),若该链表中存在一个这个的key对象,那么就直接替换其value值即可,否则在将改key-value节点插入该index索引位置处。注意,hashtable是不允许null值的。

int index = (hash & 0x7FFFFFFF) % tab.length——>键的hash值可能为负数,通过一个“与”操作,先将hash值都转化正数,然后将得到的hash值与Hashtable的长度求余

  //同步实现
public synchronized V put(K key, V value) {
// check value值是否为null
if (value == null) {
throw new NullPointerException();
} // Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
//计算key的hash值
int hash = key.hashCode();
//通过hash值来计算在table数组中的下表
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
//遍历,寻找该key,找到则替换旧值
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//没有找到,则将该key加入
addEntry(hash, key, value, index);
return null;
}
private void addEntry(int hash, K key, V value, int index) {
//修改链表,modCount自增
modCount++; Entry<?,?> tab[] = table;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
} // Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}

get方法也是同步的,具体的实现如下:

  public synchronized V get(Object key) {
Entry<?,?> tab[] = table;
//计算key的hash值
int hash = key.hashCode();
//通过hash值来计算在table数组中的下表
int index = (hash & 0x7FFFFFFF) % tab.length;
//遍历查找key,找到则返回key值所对应的的value
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return (V)e.value;
}
}
return null;
}

Java Hashtable 源码(JDK8)的更多相关文章

  1. [Java] Hashtable 源码简要分析

    Hashtable /HashMap / LinkedHashMap 概述 * Hashtable比较早,是线程安全的哈希映射表.内部采用Entry[]数组,每个Entry均可作为链表的头,用来解决冲 ...

  2. Java - HashTable源码分析

    java提高篇(二五)-----HashTable 在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,valu ...

  3. JAVA的HashTable源码分析

    Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长.Hashtable ...

  4. 转:【Java集合源码剖析】Hashtable源码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/36191279 Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元 ...

  5. 【Java集合源码剖析】Hashtable源码剖析

    转载出处:http://blog.csdn.net/ns_code/article/details/36191279 Hashtable简介 Hashtable同样是基于哈希表实现的,同样每个元素是一 ...

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

    前言 上一节我们实现了散列算法并对冲突解决我们使用了开放地址法和链地址法两种方式,本节我们来详细分析源码,看看源码中对于冲突是使用的哪一种方式以及对比我们所实现的,有哪些可以进行改造的地方. Hash ...

  7. java HashMap源码分析(JDK8)

    这两天在复习JAVA的知识点,想更深层次的了解一下JAVA,所以就看了看JAVA的源码,把自己的分析写在这里,也当做是笔记吧,方便记忆.写的不对的地方也请大家多多指教. JDK1.6中HashMap采 ...

  8. Java集合源码学习(一)集合框架概览

    >>集合框架 Java集合框架包含了大部分Java开发中用到的数据结构,主要包括List列表.Set集合.Map映射.迭代器(Iterator.Enumeration).工具类(Array ...

  9. 【转】Java HashMap 源码解析(好文章)

    ­ .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...

随机推荐

  1. opencv——阈值分割图像

    #include "stdafx.h" #include "opencv2\opencv.hpp" using namespace cv; IplImage* ...

  2. linux 系统启动

    系统启动流程 BIOS 我们称之为基本输入输出系统,一般保存在主板上的BIOS芯片中,负责检查硬件并且查找可启动设备:可设置启动顺序: 如果一个设备是可启动,那么第一个扇区512字节的最后两字节是55 ...

  3. mysql按照天或小时group分组统计

    select DATE_FORMAT( deteline, "%Y-%m-%d %H" ) , COUNT( * ) FROM test GROUP BY DATE_FORMAT( ...

  4. 【leetcode 133. 克隆图】解题报告

    方法一:dfs(递归) map<Node*,Node*> dict; Node* clone(Node* node) { if (!node) return node; if (dict. ...

  5. Sumsets(数学)

    Sumsets Time Limit: 2000MS Memory Limit: 200000K Total Submissions: 14964 Accepted: 5978 Description ...

  6. kvm虚拟化之kvm虚拟机快照备份

    kvm虚拟机默认使用raw格式的镜像格式,性能最好,速度最快,它的缺点就是不支持一些新的功能,如支持镜像,zlib磁盘压缩,AES加密等.   要使用镜像功能,磁盘格式必须为qcow2.下面开始kvm ...

  7. 如何在linux上安装使用virt-manager

    环境是centos6.5-64位操作系统. 1.准备yum源: 将CentOS6-Base-163.repo 下载到目标主机的/etc/yum.repos.d/目录. cd /etc/yum.repo ...

  8. 驼峰转大写(javaScript)

    var a = function(s){return s.replace(/([A-Z])/g,"_$1").toUpperCase();} F12控制台可以直接用

  9. Django 学习资源

    相关的分享: 开发者头条:http://toutiao.io/search?utf8=%E2%9C%93&q=django 极客头条及Django资讯:http://www.csdn.net/ ...

  10. JavaScript中setInterval的用法总结

    setInterval动作的作用是在播放动画的时,每隔一定时间就调用函数,方法或对象.可以使用本动作更新来自数据库的变量或更新时间显示. setInterval动作的语法格式如下:setInterva ...