阅读博客

java提高篇(二五)—–HashTable

这篇博客由chenssy 发表与2014年4月,基于源码是jdk1.7

==========================

本文针对jdk1.8的HashTable源码补充说明

put方法

   public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
} // Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
// 直接使用key的hashCode作为hash值。
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
} addEntry(hash, key, value, index);
return null;
}

HashTable的key和value都不能为null

HashTable不会对key的hashCode进行再哈希,直接使用。

在取table的索引时,先取hash的低31位,然后对table的长度取模。这样速度比HashMap要慢。HashMap已经考虑到这个问题,所以HashMap的table长度

是2的n次方,直接按位计算,就能得到索引,而不需要%计算了。

put使用了synchronize修饰,多线程安全。

在每次添加元素时,会判断当前元素数量是否超过了阈值,超过了,就要rehash,进行扩容。

jdk1.8 rehash源码

 protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table; // overflow-conscious code
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity]; modCount++;
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap; for (int i = oldCapacity ; i-- > 0 ;) {
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;
}
}
}

在chenssy的博客中,下面这行有笔误,少了数组的长度。

Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

jdk1.8 get方法源码

  public synchronized V get(Object key) {
Entry tab[] = table;
int hash = hash(key);
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)) {
return e.value;
}
}
return null;
}

看完了Hashtable和HashMap,发现他们的存储结构上区别是在很小,但还是有一些区别,列举如下

1,Hashtable是同步的,用synchronize修饰了get方法和put方法。而HashMap 没有这个修饰,

2,HashTable不允许key和value为null,HashMap允许。

3,HashTable使用的是Enumerator迭代器,不是fail-fast的, HashMap的迭代器更多,而且是fail-fast的。

4,他们的hash函数不同。但这个问题吧,其实就算是HashMap在不同的jdk版本中,hash函数也不同。HashTable不会对key的hashCode进行再哈希。HashMap会对key的hashCode再hash。

5,table的容量不容,HashMap的table容量总是2的n次方,这样方便了计算index值,提高了效率。HashTable的table容量比较随意,默认值是11,所以计算index时要费劲些。

HashMap在性能上要好于HashTable.

6,HashTable继承自Dictionary,实现了Map接口, HashMap继承自AbstractMap,实现了Map接口。

HashTable比较老,jdk1.0就有了

HashMap和 TreeMap jdk1.2才有

ConcurrentHashMap jdk1.5才有。

区别方面参考博客

http://www.importnew.com/7010.html (HashMap和Hashtable的区别)

Java提高(二)---- HashTable的更多相关文章

  1. java提高篇---HashTable

    在java中与有两个类都提供了一个多种用途的hashTable机制,他们都可以将可以key和value结合起来构成键值对通过put(key,value)方法保存起来,然后通过get(key)方法获取相 ...

  2. Java提高篇(二六)-----hashCode

          在前面三篇博文中LZ讲解了(HashMap.HashSet.HashTable),在其中LZ不断地讲解他们的put和get方法,在这两个方法中计算key的hashCode应该是最重要也是最 ...

  3. Java提高篇(三二)-----List总结

    前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点可以对List接口有了比较深的了解了.只有通过归纳总结的知识 ...

  4. java提高篇(二九)-----Vector

    在java提高篇(二一)-–ArrayList.java提高篇(二二)-LinkedList,详细讲解了ArrayList.linkedList的原理和实现过程,对于List接口这里还介绍一个它的实现 ...

  5. java提高篇(二四)-----HashSet

          在前篇博文中(java提高篇(二三)-----HashMap)详细讲解了HashMap的实现过程,对于HashSet而言,它是基于HashMap来实现的,底层采用HashMap来保存元素. ...

  6. java提高篇(十七)-----异常(二)

          承接上篇博文:java提高篇-----异常(一) 五.自定义异常 Java确实给我们提供了非常多的异常,但是异常体系是不可能预见所有的希望加以报告的错误,所以Java允许我们自定义异常来表 ...

  7. java提高篇(二二)-----LinkedList

    摘自http://blog.csdn.net/chenssy/article/details/18099417  java提高篇(二二)-----LinkedList 一.概述 LinkedList与 ...

  8. Java提高篇(三二)-----List总结

    前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点能够对List接口有了比較深的了解了.仅仅有通过归纳总结的知 ...

  9. 【转】java提高篇(二)-----理解java的三大特性之继承

    [转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...

随机推荐

  1. centOS 7 安装java sdk 并测试是否安装成功

    CentOS 6.X 和 7.X 自带有OpenJDK runtime environment  (openjdk).它是一个在linux上实现开源的Java 平台. 安装方式: 1.输入以下命令,以 ...

  2. CentOS下Yum使用

    1. 介绍 Yum,即Yellow dog Updater Modified,是一个基于 RPM 包管理的字符前端软件包管理器:能够从指定的服务器自动下载 RPM 包并且安装,可以处理依赖性关系,并且 ...

  3. android基本控件学习-----EditText

    EditText的讲解 一.<实例一>:用户登录 <?xml version="1.0" encoding="utf-8"?> < ...

  4. Push pull, open drain circuit, pull up, pull down resistor

    Push pull 就以下面這個 電路來說, 因為沒有 pull up resistor, 所以 output voltage 由 low 往 high 的速度會較快. 有兩個電晶體,一個on,一個 ...

  5. Matcher类详解2-group

    Matcher.group是针对()来说的,group(0)就是指的整个串,group(1) 指的是第一个括号里的东西即匹配的第一个子表达式,group(2)指的第二个括号里的东西即匹配的第二个子表达 ...

  6. Bitmap类

    一.Bitmap类 Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义的图像的对象.该类的主要方法和属性如下: 1. GetP ...

  7. map、hash_map、unordered_map 的思考

    #include <map> map<string,int> dict; map是基于红黑树实现的,可以快速查找一个元素是否存在,是关系型容器,能够表达两个数据之间的映射关系. ...

  8. 牛客练习赛10 E题 数列查找 (分块思想 + 莫队算法)

    题目链接  数列查找 考虑分块然后跑莫队, 设$c[i]$为$i$在当前维护的区间内出现的次数, $g[i]$为在当前维护的区间内有多少个数出现次数为$i$, $bg[i]$把出现次数分块,$bg[i ...

  9. Unique Binary Search Trees II - LeetCode

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  10. luogu P1345 [USACO5.4]奶牛的电信Telecowmunication

    https://www.luogu.org/problemnew/show/1345 拆点,中间建流量为1的边,跑最小割 #include<cstdio> #include<queu ...