集合专区---第9集(HashTable)

1 HashTable 结构(jdk 1.80_201)

public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

2 HashTable特点

  1. key不能为null(因为代码中需要获取key的hashCode值,不然会报空指针。)
  2. value不能为null,因为代码中做了if判断,如果为null那就抛出空指针
  3. 方法是同步的
  4. 效率相对HashMap 慢

3 整体的存储结构

  1. 结构组成:数组+单向链表

链表节点

private static class Entry<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Entry<K,V> next;
}

5 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;
    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;
}
  •  方法加了同步锁。
  •  逻辑:
  • 根据key找到数组所在的索引
  • for循环遍历链表,如果发现key相同就覆盖对应的value值,且return 之前key对应的value 值。
  • 否则 添加新的元素
6 添加新元素
private void addEntry(int hash, K key, V value, int index) {
    modCount++;//修改Map的此时+1

    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++;
}

逻辑:1 判断是否扩容 . 2 new 一个链表节点Entry,且把他的next属性设置为 数组所在index(根据key得到的索引位置)的第一个链表节点。3 新的链表节点成为了数组所在index位置的第一个链表节点

7 get方法

public synchronized V get(Object key) {//也是同步方法
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;//根据key得到的hash值获取在数组中的索引
    for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) { //循环该索引所在位置的链表结构.
        if ((e.hash == hash) && e.key.equals(key)) {
            return (V)e.value;
        }
    }
    return null;
}

8 contains 方法(containsValue方法调用的是contains方法,也就是说两个方法一模一样的)

public synchronized boolean contains(Object value) {
    if (value == null) {
        throw new NullPointerException();
    }

    Entry<?,?> tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
        for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
            if (e.value.equals(value)) {
                return true;
            }
        }
    }
    return false;
}

9 containsKey

public synchronized boolean containsKey(Object key) {
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
        if ((e.hash == hash) && e.key.equals(key)) {
            return true;
        }
    }
    return false;
}

逻辑:根据key找到hash,根据hash找到数组中的索引index,然后根据index找到链表,且循环这个单向链表。

结论:

1 HashTabel 会把新的元素添加到索引对应数组所在链表的第一个位置,也就是说新的元素不会像HashMap一样放置再链表最后面,而是在最前面。

2 没有发现红黑树结构

3 put,get,contains等方法都是同步方法

4 key,value不能为null

5 用于数据量不大(因为效率慢,数据量大的话插入所需时间会很长),且需要同步的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值