首页 / JAVA / java-map之Hashtable
java-map之Hashtable
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java-map之Hashtable,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3364字,纯文字阅读大概需要5分钟。
内容图文
1.1 概述
HashTable也是一个散列表,它存储的内容是键值对映射。HashTable继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。HashTable的函数都是同步的,这意味着它是线程安全的。它的Key、Value都不可以为null。此外,HashTable中的映射不是有序的。
1.2详解
//为一个Entry[]数组类型,Entry代表了“拉链”的节点,每一个Entry代表了一个键值对,哈希表的"key-value键值对"都是存储在Entry数组中的。
private transient Entry<?,?>[] table;
//HashTable的大小,注意这个大小并不是HashTable的容器大小,而是他所包含Entry键值对的数量。
private transient int count;
//Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值=“容量*加载因子”
private int threshold;
//加载因子。
private float loadFactor;
//用来实现“fail-fast”机制的(也就是快速失败)。所谓快速失败就是在并发集合中,其进行迭代操作时,若有其他线程对其进行结构性的修改,这时迭代器会立马感知到,并且立即抛出ConcurrentModificationException异常,而不是等到迭代完成之后才告诉你(你已经出错了)
private transient int modCount = 0;
- put方法
1.获取synchronized锁。
2.put方法不允许null值,如果发现是null,则直接抛出异常。
3.计算key的哈希值和index
4.遍历对应位置的链表,如果发现已经存在相同的hash和key,则更新value,并返回旧值。
5.如果不存在相同的key的Entry节点,则调用addEntry方法增加节点。
//获取synchronized锁
public synchronized V put(K key, V value) {
// Make sure the value is not null
//如果value是空抛出异常
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
//计算key的哈希值和index
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;
}
- get方法
1.先获取synchronized锁。
2.计算key的哈希值和index。
3.在对应位置的链表中寻找具有相同hash和key的节点,返回节点的value。
4.如果遍历结束都没有找到节点,则返回null。
public synchronized V get(Object key) {//根据键取出对应索引
Entry tab[] = table;
int hash = hash(key);//先根据key计算hash值
int index = (hash & 0x7FFFFFFF) % tab.length;//再根据hash值找到索引
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {//遍历entry链
if ((e.hash == hash) && e.key.equals(key)) {//若找到该键
return e.value;//返回对应的值
}
}
return null;//否则返回null
}
- remove方法
1.先获取synchronized锁。
2.计算key的哈希值和index。
3.遍历对应位置的链表,寻找待删除节点,如果存在,用e表示待删除节点,pre表示前驱节点。如果不存在,返回null。
4.更新前驱节点的next,指向e的next。返回待删除节点的value值。
public synchronized V remove(Object key) {
Entry<?,?> tab[] = table;
//计算key的哈希值和index
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++;
//更新前驱节点的next,指向e的next
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
V oldValue = e.value;
e.value = null;
//返回待删除节点的value值
return oldValue;
}
}
//如果不存在,返回null
return null;
}
和hashmap的主要区别:
- hashtable支持并发编程,是线程安全的。
主要是因为其底层使用了synchronized关键字。但是这样牺牲了效率。当需要多线程操作的时候也可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。 - hashtable不支持key和value为空。当出翔put(null,null)的时候会出现空指针异常。
- 扩容机制和hash值不同。
Hashtable直接使用Object的hashCode(),hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值,然后再使用去取模运算来获得最终的位置。两者的默认负载因子都是0.75,但Hashtable扩容时,容量变为原来的2倍+1,HashMap扩容时,将容量变成原来的2倍;Hashtable在不制定容量的情况下默认容量是11,也就是说Hashtable会尽量使用素数、奇数,而HashMap 的默认容量 为16,Hashtable不要求底层数组的容量为2的整数次幂,而 HashMap 要求一定为2的整数次幂。
原文:https://www.cnblogs.com/jiezao/p/13461597.html
内容总结
以上是互联网集市为您收集整理的java-map之Hashtable全部内容,希望文章能够帮你解决java-map之Hashtable所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。