hash-2.hashMap

1.HashMap的数据结构
a.HashMap是一个链表散列的结合体,即,数组和链表的结合体。
b.HashMap类中定义了Entry类型的数组,Entry [ ] ,Entry有key value hash next属性
如代码

transient Entry[] table;  

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

c.结构图如图:

d.HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,
就会初始化一个数组。table数组的元素是Entry类型的。
每个 Entry元素其实就是一个key-value对,并且它持有一个指向下一个 Entry元素的引用
,这就说明table数组的每个Entry元素同时也作为某个Entry链表的首节点,
指向了该链表的下一个Entry元素,这就是所谓的“链表散列”数据结构,即数组和链表的结合体。

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

public V put(K key, V value) {
   // HashMap允许存放null键和null值。
   // 当key为null时,调用putForNullKey方法,将value放置在数组第一个位置。
   if (key == null)
       return putForNullKey(value);
   // 根据key的keyCode重新计算hash值。
   int hash = hash(key.hashCode());
   // 搜索指定hash值在对应table中的索引。
   int i = indexFor(hash, table.length);
   // 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素。
   for (Entry<K,V> e = table[i]; e != null; e = e.next) {
       Object k;
      // 如果发现 i 索引处的链表的某个Entry的hash和新Entry的hash相等且两者的key相同,则新Entry覆盖旧Entry,返回。
       if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
           V oldValue = e.value;
           e.value = value;
           e.recordAccess(this);
           return oldValue;
       }
   }
   // 如果i索引处的Entry为null,表明此处还没有Entry。
   modCount++;
   // 将key、value添加到i索引处。
   addEntry(hash, key, value, i);
   return null; 

3.读取元素
从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,
然后通过key的equals方法在对应位置的链表中找到需要的元素。

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

4.归纳起来简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,
这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,
当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,
在根据equals方法决定其在该数组位置上的链表中的存储位置。

时间: 2024-10-26 23:42:02

hash-2.hashMap的相关文章

hash算法 (hashmap 实现原理)

Hash ,一般翻译做" 散列" ,也有直接音译为" 哈希" 的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值.简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. HASH 主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128

HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash

1.HashMap的内部实现机制 HashMap是对数据结构中哈希表(Hash Table)的实现,Hash表又叫散列表.Hash表是根据关键码Key来访问其对应的值Value的数据结构,它通过一个映射函数把关键码映射到表中一个位置来访问该位置的值,从而加快查找的速度.这个映射函数叫做Hash函数,存放记录的数组叫做Hash表. 在Java中,HashMap的内部实现结合了链表和数组的优势,链接节点的数据结构是Entry<k,v>,每个Entry对象的内部又含有指向下一个Entry类型对象的引

HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash - schbook

1.HashMap的内部实现机制 HashMap是对数据结构中哈希表(Hash Table)的实现, Hash表又叫散列表.Hash表是根据关键码Key来访问其对应的值Value的数据结构,它通过一个映射函数把关键码映射到表中一个位置来访问该位置的值,从而加快查找的速度.这个映射函数叫做Hash函数,存放记录的数组叫做Hash表. 在Java中,HashMap的内部实现结合了链表和数组的优势,链接节点的数据结构是Entry<k,v>,每个Entry对象的内部又含有指向下一个Entry类型对象的

HashMap原理-1.7

之所以分两篇文章记录,因为之前一直看的1.7的源码,而且网上很多的都是关于1.7的,今天在1.8上打开源码一看,居然懵了.    没想到1.8的实现变化这么大.所有特地拿一篇文章来记录下. 本章只介绍1.7的情况 1.HashMap存储结构 哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点.那么这些元素是按照什么样的规则存储到数组中呢.一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到.比如上述哈希表中,12%16=12

HashMap的实现原理

hash算法 (hashmap 实现原理) Java实现的散列表 1.HashMap的数据结构 数组的特点是:寻址容易,插入和删除困难:而链表的特点是:寻址困难,插入和删除容易.那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法-- 拉链法,我们可以理解为"链表的数组" ,如图: 从上图我们可以发现哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的

HashMap VS BST

HashMap usually performs search operations bounded with complexity of O(1)<=T(n)<=O(n). BST performs search operations in O(logN)<=T(n)<=O(N). HashMap is implemented with array and hash function. HashMap has O(1) lookup time when the hashcode

关于Android中SparseArray比HashMap性能好的深入研究

由于网上有朋友对于这个问题已经有了很详细的研究,所以我就不班门弄斧了: 转载于:http://android-performance.com/android/2014/02/10/android-sparsearray-vs-hashmap.html http://liuzhichao.com/p/832.html SparseArray是Android框架独有的类,在标准的JDK中不存在这个类.它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为

Android应用性能优化之使用SparseArray替代HashMap

一.概述 最近在项目中看到了SparseArray,好奇研究了下. SparseArray是Android框架独有的类,在标准的JDK中不存在这个类.它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseArray不需要对key和value进行auto-boxing(将原始类型封装为对象类型,比如把int类型封装成Integer类型),结构比HashMap简单(SparseArray内部主要使用两个一维数组来保存数据,一个用来存key,一

Hash算法初见

hash算法 (hashmap 实现原理) Hash ,一般翻译做“ 散列” ,也有直接音译为“ 哈希” 的,就是把任意长度的输入(又叫做预映射, pre-image ),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值.简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. HASH 主要用于信息安全领域中加密算法,它把一些不同长度的信息转

nyoj 904 hashmap

这个题目是个水题目,现在我只管做出来,效率不考虑了. 题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=904 我用hashmap 很爽,很简单,但效率很低,别人有的是用二分查找,不管了, package nyoj904; import java.util.HashMap; import java.util.Scanner; public class Main { public static void main(String[] arg