【数据结构】9.java源码关于HashTable
1.hashtable的内部结构
基础存储数据的hash桶由Entry结构的数组存放
而entry数据结构,有hash,key和value,还有一个指向下一个节点的引用next对象
这里就和hashmap中的数据结构不一样了,hashmap中的数据结构是node,虽然结构上差不多,但是setvalue的非空判断和hashcode的散列取值都是和node不一样的
那么这些数据在什么时候用呢???
下面来一一了解
2.hashtable的构造函数
这里需要注意一下了,我们前面提到说hashmap中的构造函数,其实实际上是不对hash桶进行实例化的,但是hashtable不一样,他会直接实例化大小,并且实例化成你指定的大小
而且这里默认的初始化容器的大小是11,负载因子代销默认0.75,负载因子的作用就是规定最大容量:hash桶的大小*负载因子
public TestHashTable(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); //至少设置为1
if (initialCapacity==0)
initialCapacity = 1;
this.loadFactor = loadFactor;
table = new Entry<?,?>[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}
3.hashtable的增加元素策略
1.这里的put方法加了synchronized修饰符,用来标识线程安全
2.这里进行put取索引位置的时候,是直接用的key的hashcode方法,并且对hashcode结果进行取正数(& 0x7FFFFFFF),然后对hash桶进行取余%
然后就是判断这个key是否存在于这个hash桶中,如果存在更新旧值,并返回旧值
不存在,那么就添加一个entry,所以put操作的关键就是addEntry
而我们add操作其实就是找到对应的散列位置,然后用头插法
private void addEntry(int hash, K key, V value, int index) {
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++;
}
说实话,这里相比hashmap来说简单多了,主要是少了树化的操作
4.hashtable删除元素策略
删除就比较简单了,就是找到对应的索引位置,然后再查找链表,如果是头节点,直接把entry.next设置为索引位置的数据,如果不是,就要获取到pre节点,然后pre.next = entry.next
public synchronized V remove(Object key) {
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
V oldValue = e.value;
e.value = null;
return oldValue;
}
}
return null;
}
主要是for循环这个地方有点意思,其余的到还好,无非就是返回旧值而已
5.修改元素,查找元素
修改不多做操作了,和添加,删除操作差不多,只是没有里面的多余操作,就是找到元素就直接返回了
6.hashtable特殊操作
1.hashtable是允许放空键值的,也就是键和值都可以放null
2.还有hashtable是线程安全的
3.hashmap再1.8之后是数组+链表+红黑树,hashtable还是很光棍-》数组+链表
4.扩容需要说一下,hashmap会扩容到比设置值大的最小2次幂,hashtable就群魔乱舞随意了
5.hashmap和hashtable都是取余,但是有点不同,因为hashmap是2次幂,所以取余的方式不一样是:(n - 1) & hash,为什么这样,请复习hashmap源码分析。。。
7.hashtable的刷新扩容
protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table; //直接左移一位,也就是扩大2倍然后+1 =》 大小扩为 2n + 1
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) { //Integer.MAX_VALUE - 8
if (oldCapacity == MAX_ARRAY_SIZE) //如果老的容量已经达到这个值,anemia继续保持
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE; //否则设置为允许的最大值
}
//创建新的hash桶
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; modCount++;
//设置新的阈值
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap; //遍历hash桶,从后往前
for (int i = oldCapacity ; i-- > 0 ;) {
//遍历所有索引下的链表,吧链表添加到新的hash桶上
for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next; //先取正,然后取余
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
总结一下吧:
说实话,看完hashtable没花多久时间,相比较hashmap给人的惊为天人的操作,hashtable相对来说就比较朴实无华了,唯一的几个亮点就是线程安全,然后。。。。
想不出来了,只能说存在即合理,不能说hashtable会比较low,也许是我眼拙,大道至简,也许没有那些花里胡哨的才是真正最实用的
参考:
https://juejin.im/post/5a03b258518825188e515d89
https://blog.csdn.net/yyc1023/article/details/80619623
【数据结构】9.java源码关于HashTable的更多相关文章
- java源码阅读Hashtable
1类签名与注释 public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, C ...
- 如何阅读Java源码 阅读java的真实体会
刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比 ...
- 如何阅读Java源码
刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动.源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧, ...
- Java 源码学习线路————_先JDK工具包集合_再core包,也就是String、StringBuffer等_Java IO类库
http://www.iteye.com/topic/1113732 原则网址 Java源码初接触 如果你进行过一年左右的开发,喜欢用eclipse的debug功能.好了,你现在就有阅读源码的技术基础 ...
- [收藏] Java源码阅读的真实体会
收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我 ...
- Java源码解读(一)——HashMap
HashMap作为常用的一种数据结构,阅读源码去了解其底层的实现是十分有必要的.在这里也分享自己阅读源码遇到的困难以及自己的思考. HashMap的源码介绍已经有许许多多的博客,这里只记录了一些我看源 ...
- 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法
注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...
- 如何阅读Java源码?
阅读本文大概需要 3.6 分钟. 阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃< ...
- Java源码阅读的真实体会(一种学习思路)
Java源码阅读的真实体会(一种学习思路) 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈 ...
随机推荐
- 个人永久性免费-Excel催化剂功能第60波-数据有效性验证增强版,补足Excel天生不足
Excel在数据处理.数据分析上已经是公认的最好用的软件之一,其易用性和强大性也吸引无数的初中高级用户每天都在使用Excel.但这些优点的同时,也带出了一些问题,正因为其不同于一般的专业软件,需要专业 ...
- 面试题((A)null).fun()——java中null值的强转
面试题分享 public class A {public static void fun1() { System.out.println("fun1"); } public voi ...
- python以ATM+购物车剖析一个项目的由来及流程
ATM+购物车 一个项目是如何从无到有的 ''' 项目的由来,几个阶段 0.采集项目需求 1.需求分析 2.程序的架构设计 3.分任务开发 4.测试 5.上线运行 ''' 需求分析: # 对项目需求进 ...
- 四、利用SQL Server 2008 R2创建自动备份计划
(转) 本文主要利用SQL Server 2008 R2自带的"维护计划"创建一个自动备份数据的任务. 首先,启动 Sql Management studio,确保"SQ ...
- C#中线程间操作无效: 从不是创建控件 txtBOX 的线程访问它。
delegate void 委托名(方法名); void 方法名() { if(txtBox.invokeRequered) { 委托名 d=new 委托名(); txtBox.invoke(d); ...
- 用JSP从数据库中读取图片并显示在网页上
<1>先在mysql下建立如下的table. 并insert图像. mysql.sql文件如下: CREATE TABLE photo ( photo_no int(6) unsigned ...
- LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素
题目 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数字. 您能 ...
- 腾讯位置服务API快速入门
前言 之前项目有个需求,在网页上显示微信发送过来的位置信息,该开始想用百度地图,后来发现腾讯地图相对简单一点 快速入门 申请Key https://lbs.qq.com/guides/startup. ...
- 完美解决windows10磁盘占用100%并出现卡顿、假死无反应
完美解决windows10磁盘占用100%并出现卡顿.假死无反应 想必大家也跟我一样,自从用win10系统以后经常会出现这种情况:磁盘突然占用100%然后开始出现假死现象,电脑卡住,点击任何软件没反应 ...
- java遍历所有目录和文件
package xian; import java.io.File; import java.util.ArrayList; public class GetFile { private static ...