JVM里面hashtable和hashmap实现原理

来源:互联网 发布:淘宝默认好评是几天 编辑:程序博客网 时间:2024/05/27 06:51

整理下

用一句话来说:

就是用一个数组,每个元素可能存储一个entry链表,存储每个entry的时候先计算key的hash值与数组长度取模%即可得到所在数组的位置下标。


Hashtable与HashMap是怎么实现hash键值对配对的呢?

利用  hashtable 的构造方法  get(Object) put(K,V)

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)(initialCapacity * loadFactor);
    }

这个里面米内有什么好说的,要注意的是table一个是实体数组,输入的initialCapacity表示这个数组的大小,而threshold 是一个int值,其中loadFactor默认是0.75,就是说明,当table里面的值到75%的阀值后,快要填满数组了,就会自动双倍扩大数字容量.

   而Entry<K,V> 来自与

private static class Entry<K,V> implements Map.Entry<K,V> {
            int hash;
            K key;
            V value;
            Entry<K,V> next;
是一个单项链表,

二、put(K, V)加入方法

   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;
 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
   V ld = e.value;
   e.value = value;
  return old;
     }
 }

 modCount++;
  if (count >= threshold) {
      // Rehash the table if the threshold is exceeded
      rehash();

             tab = table;
             index = (hash & 0x7FFFFFFF) % tab.length;
 }

  // Creates the new entry.
  Entry<K,V> e = tab[index];
 tab[index] = new Entry<K,V>(hash, key, value, e);
 count++;
 return null;
     }

这个看看起来很长,只要注意三点就可以了,

1.index,index是键值的hashcode和0x7FFFFFFF的&运算,然后根据数组长度求余值。这样可以定出所在队列名称,

2、

 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
     if ((e.hash == hash) && e.key.equals(key)) {
  V ld = e.value;
  e.value = value;
  return old;
     }
 }

for语句里面是让e在tab某个队列名为index单项链表里面遍历,第几个单项链表的定义由index定义,看看该队列是否已经有同样的值,如果有,就返回该值。

3、如果没有,则加入

 Entry<K,V> e = tab[index];
 tab[index] = new Entry<K,V>(hash, key, value, e);

三、get(Object),获得

    public synchronized V get(Object key) {
 Entry tab[] = table;
 int hash = key.hashCode();
 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;
    }

这个就很好理解了 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;
     }
 }

在该队里面遍历,根据hash值获得具体值。

 

总结下,一个是根据index确定队列,在由hash值获得具体元素值。

 

看完了hashtable, 我们在来看看hashMap
hashMap可以算作是hashtable的升级版本, 最早从1.2开始有的. 

但是, 两者之间最主要的不同有两点.
1.     hashMap的读写是unsynchronized, 在多线程的环境中要注意使用
而hashtable是synchronized
这两者的不同是通过在读写方法上加synchronized关键字来实现的.

第二个不同是hashMap可以放空值, 而hashtable就会报错.



0 0
原创粉丝点击