zoukankan      html  css  js  c++  java
  • HashMap

       HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是不能保证该顺序恒久不变。

       HashMap的数据结构:

       在java中,最基本的结构有两种:一是数组,而是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

      

    HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap时,就会初始化一个数组。

    1 transient Entry[] table;
    2 static class Entry<k,V> implements Map.Entry<K,V>{
    3     final K key;
    4     V value;
    5     Entry<K,V> next;
    6     final int hash;
    7     ......
    8 }

    可以看出,Entry就是数组中的元素,每个Map.Entry其实就是一个key-value对,它持有一个指向下一个元素的引用,这就构成了链表。

      HashMap的存取实现:

      1)存储:

     1 public V put(K key,V value){
     2     //HashMap允许存放null值和null键
     3     //当key为null时,调用putForNullKey方法,将value放置在数组的一个位置。
     4     if(key==null)
     5         return putForNullKey(value);
     6     //根据key的hashCode重新计算hash值
     7     int hash=hash(key.hashCode());
     8     //搜索指定hash值在对应table中的索引
     9     int i=indexFor(hash,table.length);
    10     //如果i索引处的Entry不为null,通过循环不断遍历e元素的下一个元素。
    11     for(Entry<K,V> e=table[i];e!=null;e=e.next){
    12         Object k;
    13         if(e.hash==hash&&((k=e.key)==key||key.equals(k))){
    14             V oldValue = e.value;
    15             e.value = value;
    16             e.recordAccess(this);
    17             return oldValue;
    18         }
    19     }
    20 // 如果i索引处的Entry为null,表明此处还没有Entry。
    21     modCount++;
    22     // 将key、value添加到i索引处。
    23     addEntry(hash, key, value, i);
    24     return null;
    25 }

    从上面的源码中可以看出:当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放了其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

      2)读取:

    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
            e != null;
            e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

    有了上面存储时的hash算法作为基础,理解起来这段代码就很容易了。从上面的源代码中可以看出:从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。

      以上内容摘抄自http://beyond99.blog.51cto.com/1469451/429789

        

    HashMap使用了特殊的值,称作散列码,来取代对键的缓慢搜索。散列码是“相对唯一”的、用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。hashCode()是根类Object中的方法,因此所有的Java对象都能产生散列码。HashMap就是使用对象的hashCode()进行快速查询的,此方法能显著提高性能。

  • 相关阅读:
    etcd的原理分析
    (转)Linux sort命令
    随机森林
    python 类的定义和继承
    python random
    Spark源码阅读(1): Stage划分
    Mac 上安装MySQL
    Python 删除 数组
    在循环中将多列数组组合成大数组
    准确率 召回率
  • 原文地址:https://www.cnblogs.com/dazuihou/p/3576352.html
Copyright © 2011-2022 走看看