HashTable 认识:

  1. 底层使用散列表,存贮键值对,键值非null
  2. 使用synchronize 保证线程安全
  3. 如果多线程高发量,推荐使用 concurrentHashMap; 如无需多线程,可使用 HashMap

■ 重要全局变量

//The hash table data.
//底层维护一个Entry(键值对)数组
private transient Entry<K,V>[] table;
//The total number of entries in the hash table.
//元素总量,等同于HashMap的size
private transient int count;
//The load factor for the hashtable.
//负载因子
private float loadFactor;
/**
* The table is rehashed when its size exceeds this threshold.
* (The value of this field is (int)(capacity * loadFactor).)
* 超过阈值进行rehash
*/
private int threshold;
/**
* The number of times this Hashtable has been structurally modified
* Structural modifications are those that change the number of entries in
* the Hashtable or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the Hashtable fail-fast. (See ConcurrentModificationException).
* 结构性变动时modCount计数+1,用于遍历时的fail-fast机制生效
*/
private transient int modCount = 0

■ 构造函数

/**
* Constructs a new, empty hashtable with the specified initial
* capacity and the specified load factor.
*/
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; //没有强调2次幂,cap为0时,默认是1
this.loadFactor = loadFactor;
table = new Entry<?,?>[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
} /**
* Constructs a new, empty hashtable with a default initial capacity (11)
* and load factor (0.75).
* 容量11,负载因子 0.75
*/
public Hashtable() {
this(11, 0.75f);
}

■主要方法 (基本都是 syn 修饰)

- put(K key, V value)

public synchronized V put(K key, V value) {
// Make sure the value is not null,而HashMap选择将key为null永远存放为table[0]位置
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
//确保key不在hashtable中
//首先,通过hash方法计算key的哈希值,并计算得出index值,确定其在table[]中的位置
//其次,迭代index索引位置的链表,如果该位置处的链表存在相同的key,则替换value,返回旧的value
Entry tab[] = table;
int hash = hash(key);
//计算下标,这里使用%方法,性能远不及HashMap的位运算 (这也是不推荐使用HashTable的原因之一)
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
//直接使用equals比较,而HashMap多了一层地址比较 `((k = e.key) == key || key.equals(k))`
if ((e.hash == hash) && e.key.equals(key)) {
V old = e.value;
e.value = value;
return old;
}
}
//结构性变更操作 modCount计数+1
modCount++;
//HashMap选择新增addEntry方法封装一下逻辑
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
//如果超过阀值,就进行rehash操作
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
//将值插入,返回的为null
Entry<K,V> e = tab[index];
// 创建新的Entry节点,并将新的Entry插入Hashtable的index位置,并设置e为新的Entry的下一个元素
tab[index] = new Entry<>(hash, key, value, e);
//size++
count++;
return null;
}

- get(Object key)

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 遍历

/**
* Created by roman on 2017/10/03.
*【2017 java's day】
*/
public class ListHashTableTest {
public static void main(String[] args) {
Hashtable<String, Object> hb = new Hashtable<String, Object>();
hb.put("1", "Java");
hb.put("flag", true);
hb.put("age", 44); Iterator iterator = hb.keySet().iterator();
iterator.forEachRemaining(value -> System.out.println(hb.get(value))); //使用了lamda
}
}

■ HashTable VS HashMap

  • HashTable 基于 Dictionary 类,而 HashMap 是基于 AbstractMap。Dictionary 是任何可将键映射到相应值的类的抽象父类,而 AbstractMap 是基于 Map 接口的实现,它以最大限度地减少实现此接口所需的工作.
  • HashMap 的 key 和 value 都允许为 null,而 Hashtable 的 key 和 value 都不允许为 null。HashMap 遇到 key 为 null 的时候,调用 putForNullKey 方法进行处理(统一放入table[0]位置),而对 value 没有处理;Hashtable遇到 null,直接返回 NullPointerException.
  • Hashtable 方法是同步,而HashMap则不是。Hashtable 中的几乎所有的 public 的方法都是 synchronized 的,而有些方法也是在内部通过 synchronized 代码块来实现。
  • HashTable由于使用sync和%运算(以及相关算法实现)的缘故,相比于HashMap,性能较低,因此非常不推荐继续使用HashTable。
  • 非竞争环境下推荐使用HashMap。
  • 多线程环境下推荐使用ConcurrentHashMap。

最新文章

  1. JavaScript--面向对象--猜拳游戏
  2. jQuery之ready源码分析
  3. Python读取文本,输出指定中文(字符串)
  4. 利用 Django REST framework 编写 RESTful API
  5. Linq 中的 left join
  6. BZOJ 4596: [Shoi2016]黑暗前的幻想乡
  7. JS时间自动更新
  8. RSS
  9. 转: 最值得阅读学习的 10 个 C 语言开源项目代码
  10. background-image中url找不到路径,背景图像无法显示
  11. WebSocket 浅析
  12. 一道关于比赛胜负的Sql查询题目
  13. Spring+Maven+Eclipse构建Web工程
  14. DotNet中的计时器线程计时器
  15. 移动端车牌识别——可以嵌入智能手机系统里的新OCR识别技术
  16. Flutter 异常处理之图片篇
  17. DUMP 5 企业级电商项目
  18. docker 恶意镜像到容器逃逸影响本机
  19. Tomcat 7.0安装与配置
  20. Mysql数据库 的库表简易操作

热门文章

  1. 如何在环境变量里配置tomcat
  2. 框架整合——Spring与MyBatis框架整合
  3. javascript实现jsp页面的打印预览
  4. java TreeSet应用
  5. 网络协议UDP
  6. JavaScript在应用中的技巧(一)
  7. 在数组a中,a[i]+a[j]=a[k],求a[k]的最大值,a[k]max——猎八哥fly
  8. js数组、内置对象、自定义对象
  9. CentOS6.5下LNMP环境的搭建
  10. 【Beta】 第一次Daily Scrum Meeting