Java Hashtable 源码分析

2019-12-18  本文已影响0人  Java技术分享45

Hashtable 提供的功能

Hashtable 涉及到的概念

Hashtable常用方法分析

处理 Hash冲突

Hashtable 处理 Hash冲突 时通过单链表。。

涉及的基本概念

存在未理解之处

Hashtable的count字段是什么时候初始化的?从赋值来看是通过readObject()方法来实现的。但是具体实现需要回去取研读下《Java编程思想》序列化章节内容。

private transient int count;

未理解之处的解答

模拟hash冲突

可以根据hash函数(key.hashCode() & 0x7FFFFFFF) % key数组现在的长度来模拟hash冲突,只要key的hashCode是相同但是又不equals()的就是Hash冲突。如下实例:

public class MyKey implements Serializable {
    private int i;

    public MyKey(int i) {
        this.i = i;
    }

    @Override
    public int hashCode() {
        if (i % 2 == 0) {
            return 1;
        } else {
            return 2;
        }
    }

}

Hashtable处理hash冲突

如下实例:

public static void main(String[] args) {
    Hashtable<MyKey, Integer> map = new Hashtable<>();
    for (int i = 0; i < 11; i++) {
        map.put(new MyKey(i), i);
    }
    map.get(new MyKey(1));
}

如何在IDEA调试模式下查看储存结构?

Hashtable在IDEA下的默认视图:


Java-Hashtable-data-structure-default-view.png

如何查看对象视图?如下图操作:

Java-Hashtable-data-structure-object-view.png

对象视图如下

Java-Hashtable-data-structure.png

从如上对象视图可以看出Hashtable的table字段的具体存储方式:
table数组中有两个元素,一个是MyKey.i=10,一个是Mykey.i=9,按如上查看对象视图的方法查看这两个元素的对象视图查看java.util.Hashtable.Entry#next属性,可以看到MyKey.i=10的next属性值是MyKey.i=8...
各元素的具体结构如下:

MyKey.i=10.next -> MyKey.i=8
MyKey.i=8.next -> MyKey.i=0
MyKey.i=0.next -> MyKey.i=2
MyKey.i=2.next -> MyKey.i=4
MyKey.i=4.next -> MyKey.i=6
MyKey.i=6.next -> null


MyKey.i=9.next -> MyKey.i=1
MyKey.i=1.next -> MyKey.i=3
MyKey.i=3.next -> MyKey.i=5
MyKey.i=5.next -> MyKey.i=7
MyKey.i=7.next -> null

为什么顺序不是按加入的顺序的呢,而是一部分到过来的?
因为Hashtable的key数组默认大小是11,当加入11个元素时,会自动扩容,在加入第8个元素时会rehash一次,rehash时是将新哈希表中的元素作为后面加入元素的next的,所有就会出现部分元素顺序相反。

上一篇下一篇

猜你喜欢

热点阅读