>

java集合-HashTable,java-hashtable

- 编辑:正版管家婆马报彩图 -

java集合-HashTable,java-hashtable

java集合-HashTable,java-hashtable

概述

和 HashMap 相近,Hashtable 也是一个散列表,它存款和储蓄的内容是键值对。

Hashtable 在 Java 中的定义为:

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

 从源码中,大家得以看出,Hashtable 承接于 Dictionary 类,达成了 Map, Cloneable, java.io.塞里alizable接口。个中Dictionary类是此外可将键映射到相应值的类(如 Hashtable)的空洞父类,每一个键和值都以对象.

成员变量

Hashtable是经过"拉链法"实现的哈希表。它总结多少个重大的成员变量:table, count, threshold, loadFactor, modCount。

  • table是一个 Entry[] 数组类型,而 Entry(在 HashMap 中有疏解过)实际上便是一个单向链表。哈希表的"key-value键值对"都以积攒在Entry数组中的。
  • count 是 Hashtable 的深浅,它是 Hashtable 保存的键值对的数据。
  • threshold 是 Hashtable 的阈值,用于判定是或不是需求调动 Hashtable 的体积。threshold 的值="容积*加载因子"。
  • loadFactor 正是加载因子。

modCount 是用来贯彻 fail-fast 机制的。

/**
     * The hash table data.
     */
    private transient Entry<K,V>[] table;

    /**
     * The total number of entries in the hash table.
     */
    private transient int count;

    /**
     * The table is rehashed when its size exceeds this threshold.  (The
     * value of this field is (int)(capacity * loadFactor).)
     *
     * @serial
     */
    private int threshold;

    /**
     * The load factor for the hashtable.
     *
     * @serial
     */
    private float loadFactor;

    /**
     * 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).
     */
    private transient int modCount = 0;

构造方法

Hashtable 生龙活虎共提供了 4 个构造方法:

    • public Hashtable(int initialCapacity, float loadFactor): 用内定起始体量和点名加载因子构造二个新的空哈希表。useAltHashing 为 boolean,其要是为真,则施行另后生可畏散列的字符串键,以减小是因为弱哈希总结导致的哈希冲突的爆发。
    • public Hashtable(int initialCapacity):用钦赐初阶容积和暗中认可的加载因子 (0.75) 构造一个新的空哈希表。
    • public Hashtable():暗许构造函数,容积为 11,加载因子为 0.75。
    • public Hashtable(Map<? extends K, ? extends V> t):构造三个与给定的 Map 具备同等映射关系的新哈希表。
/**
     * Constructs a new, empty hashtable with the specified initial
     * capacity and the specified load factor.
     *
     * @param      initialCapacity   the initial capacity of the hashtable.
     * @param      loadFactor        the load factor of the hashtable.
     * @exception  IllegalArgumentException  if the initial capacity is less
     *             than zero, or if the load factor is nonpositive.
     */
    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;
        this.loadFactor = loadFactor;
        table = new Entry[initialCapacity];
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        useAltHashing = sun.misc.VM.isBooted() &&
                (initialCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
    }

    /**
     * Constructs a new, empty hashtable with the specified initial capacity
     * and default load factor (0.75).
     *
     * @param     initialCapacity   the initial capacity of the hashtable.
     * @exception IllegalArgumentException if the initial capacity is less
     *              than zero.
     */
    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    /**
     * Constructs a new, empty hashtable with a default initial capacity (11)
     * and load factor (0.75).
     */
    public Hashtable() {
        this(11, 0.75f);
    }

    /**
     * Constructs a new hashtable with the same mappings as the given
     * Map.  The hashtable is created with an initial capacity sufficient to
     * hold the mappings in the given Map and a default load factor (0.75).
     *
     * @param t the map whose mappings are to be placed in this map.
     * @throws NullPointerException if the specified map is null.
     * @since   1.2
     */
    public Hashtable(Map<? extends K, ? extends V> t) {
        this(Math.max(2*t.size(), 11), 0.75f);
        putAll(t);
    }

put 方法

put 方法的满贯工艺流程为:

下边包车型地铁代码中也进行了有些注明:

public synchronized V put(K key, V value) {
        // Make sure the value is not null确保value不为null
        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);
        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)) {
                V old = e.value;
                e.value = value;
                return old;
            }
        }

        modCount++;
        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);
        count++;
        return null;
    }

经过一个实在的事例来演示一下以此进度:

万少年老成大家前几天Hashtable的体积为5,已经存在了(5,5),(13,13),(16,16),(17,17),(21,21)这5 个键值对,近期他俩在Hashtable中之处如下:

图片 1

方今,大家插入一个新的键值对,put(16,22),假若key=16的目录为1.但这两天索引1的岗位有四个Entry了,所以程序会对链表举行迭代。迭代的进程中,开掘内部有四个Entry的key和大家要插入的键值对的key肖似,所以未来会做的行事便是将newValue=22替换oldValue=16,然后回来oldValue=16.

图片 2

接下来我们现在再插入三个,put(33,33),key=33的目录为3,而且在链表中也荒诞不经key=33的Entry,所以将该节点插入链表的第二个任务。

图片 3

get 方法

相比较于 put 方法,get 方法规轻便非常多。其进程正是首先通过 hash()方法求得 key 的哈希值,然后依据 hash 值获得 index 索引(上述两步所用的算法与 put 方法都一点差异也未有)。然后迭代链表,再次回到相称的 key 的应和的 value;找不到则赶回 null。

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

Hashtable 有种种遍历情势:

//1、使用keys()
Enumeration<String> en1 = table.keys();
    while(en1.hasMoreElements()) {
    en1.nextElement();
}

//2、使用elements()
Enumeration<String> en2 = table.elements();
    while(en2.hasMoreElements()) {
    en2.nextElement();
}

//3、使用keySet()
Iterator<String> it1 = table.keySet().iterator();
    while(it1.hasNext()) {
    it1.next();
}

//4、使用entrySet()
Iterator<Entry<String, String>> it2 = table.entrySet().iterator();
    while(it2.hasNext()) {
    it2.next();
}

Hashtable 与 HashMap 的简要比较

概述 和 HashMap 同样,Hashtable 也是七个散列表,它存款和储蓄的始末是键值对。 Hashtable 在 Java 中的定义为: public cla...

本文由关于计算机发布,转载请注明来源:java集合-HashTable,java-hashtable