• JVM里面hashtable和hashmap实现原理


    JVM里面hashtable和hashmap实现原理

     
    文章分类:Java编程

    转载

    在hashtable和hashmap是java里面常见的容器类,

    是Java.uitl包下面的类,

    那么Hashtable和Hashmap是怎么实现hash键值对配对的呢,我们看看jdk里面的源码,分析下Hashtable的构造方法,put(K, V)加入方法和get(Object)方法就大概明白了。

    一、Hashtable的构造方法:Hashtable(int initialCapacity, float loadFactor)

        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;
    是一个单项链表,

    上图就是Hashtable的表,

    二、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就会报错.

  • 相关阅读:
    ASP.NET的底层体系1
    MVC路由解析---IgnoreRoute
    HTTP协议详解(三)
    HTTP协议详解(二)
    HTTP协议详解(一)
    优化MySQL服务器
    知识管理系列---3.程序实现
    Linux上PHP加入环境变量
    php-fpm 服务
    centos 服务器编译安装apache+php
  • 原文地址:https://www.cnblogs.com/downey/p/4888405.html
Copyright © 2020-2023  润新知