`
dxm1986
  • 浏览: 435212 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HashMap学习随笔

阅读更多

HashMap用的常有,但深入了解HashMap源码,数据结构,实现原理的人应该相对较少。今天闲暇之余,对HashMap的源码研究了一下。

 

HashMap在JAVA开发中,经常用到,需要使用键值对,但无需同步的,可以快速查找其中的元素,那么HashMap是怎么达到其快速定位无素的的呢?

 

1 首先谈一下HashMap的数据结构

HashMap是一个由数据与链表构成的一种存储结构,水平方向是一种数组,页每个数组都是一个链表的头部。如下图:



上图中,X轴方向为HashMap的数组容器,Y轴方向,为每个相应位置的单向链表。每一个元素都是一个包含如图所示四个属性,key,value,hash,next的一种数据结构,即EntrySet,其中的next指向Y轴方向其下一个元素.

现在知道HashMap的数据结构了,那么其实现又是怎么样的?

 

 

2 HashMap的实现

 

首先看一下HashMap的构造函数(可能用的比较多的是,无参构造函数)

public HashMap(int initialCapacity, float loadFactor) {

        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }
 

 

loadFactor :加载因子,加载因子与HashMap resize有关。默认为0.75

capacity:容器大小,默认值为16 其大小为上面所说的数据结构中数组的长度。

table:即为上面数据结构图中,X方向的数组(transient Entry[] table;

threshold :resize的临界值,即当HashMap中无素个数达到该值时,HashMap就会调用其resize方法,重新扩充大小。

 

从下面的代码中:

 

 

  while (capacity < initialCapacity)
            capacity <<= 1;

 

可以看出,capacity的值是2的倍数,为什么?为什么?在下面我会讲到。

 

创建HashMap之后,我们得到了一个空的hashMap容器,我们接下来的可能就是往容器里面放我们的元素了。

public V put(K key, V value) 

 

 

 

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

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
 

当你的key为null时,会调用putForNullKey,HashMap允许key为null,这样的对像是放在table[0]中。

如果不为空,则调用int hash = hash(key.hashCode());这是hashmap的一个自定义的hash,在key.hashCode()基础上进行二次hash

 

static int hash(int h) {
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
 

这样做的目的就是为了改进传统的hash方法,而且尽量保证key的每一位都会影响到最后的hash值,以达到减少hash冲突的目的.再看indexFor方法:

hashMap是根据这个方法定位到某个元素,将要存储在X方向,即table数组的哪个位置。

 

 

 static int indexFor(int h, int length) {
        return h & (length-1);
    }
 

 

就一行代码,将key的二次hash值,与长度减一进行与操作,这一步可谓经典,通常我们会用取模的方式来定位数组中的某个位置,但是hashMap却用这种方法,而且length即capacity的值,面capacity又是2的倍数,减1之后,表示成二进制就全部是1了,那么与全部为1的一个数进行与操作,速度会大大提升了。这就是为什么"capacity的值是2的倍数"

 

位定到具体的列之后,hashMap会遍历该列的所有元素,当以该key的无素已经存在是,会将其value替换,并返回其原值。否则会重新创建一个新的EntrySet并放在table[indexFor(hash, table.length)]的位置上,并将之前该列的链表,设为其next。最后是判断hashmap中元素的个数是否达到了threshold ,如果达到了则将其容器扩大到原来的2倍。如下所示:

 

 resize(2 * table.length);
 

 

当然hashMap的get 方法,是首先通过通过key的两次hash值与数组的长度(capacity)进行于操作,定位到数组的某个位置,然后对该列的链表进行遍历,一般情况下,hashMap的这种查找速度是非常快的,hash值相同的元素过多,就会造成链表中数据很多,而链表中的数据查找是通过遍历所有链表中的元素进行的,这可能会影响到查找速度,找到即返回,这里需要注意的是,返回为null时,你不能判断是找到了,还是在hashmap中存着一个value为null的元素,因为hashmap允许value为null.

 

HashMap有一些比较重新的方法,比如resize,putAll,remove等,我都认真的看过。感觉代码写的非常精致。希望有兴趣的朋友也认直的去看一下。

 

 

说到HashMap不是线程完全的情况,可以用Map Collections.synchronizedMap(Map m) 或者HashTable去实现。

 

  • 大小: 8.4 KB
  • 大小: 45.9 KB
0
0
分享到:
评论

相关推荐

    马士兵老师HashMap学习笔记

    《马士兵老师HashMap学习笔记详解》 HashMap是Java编程语言中常用的一种数据结构,它提供了键值对(key-value pair)的存储功能,是基于哈希表实现的。马士兵老师的HashMap学习笔记深入剖析了这一核心组件的工作...

    hashmap面试题_hashmap_

    《HashMap面试题详解》 HashMap作为Java集合框架中的重要成员,是面试中常见的知识点,尤其在数据结构与算法、并发编程以及JVM内存管理等领域,HashMap的深入理解至关重要。本篇将围绕HashMap的相关面试题,从基础...

    HashMap介绍和使用

    ### HashMap介绍和使用详解 #### 一、HashMap的数据结构 HashMap是Java集合框架的一个重要组成部分,它实现了Map接口,能够存储键值对映射。在Java编程语言中,最基本的数据结构有两种:数组和引用(模拟指针)。...

    深入Java集合学习系列:HashMap的实现原理

    在Java编程语言中,集合框架是开发者日常工作中不可或缺的一部分,HashMap作为其中的重要成员,它的实现原理对于理解Java性能优化和数据结构有深远的意义。HashMap是一个基于哈希表的数据结构,它实现了Map接口,...

    hashmap实现原理

    哈希映射(HashMap)是Java编程语言中广泛使用的数据结构之一,主要提供键值对的存储和查找功能。HashMap的实现基于哈希表的概念,它通过计算对象的哈希码来快速定位数据,从而实现了O(1)的平均时间复杂度。在深入...

    HashMap之resize()方法源码解读.docx

    HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...

    深入解读大厂java面试必考点之HashMap全套学习资料

    本套学习资料全面涵盖了HashMap的深入解析,旨在帮助求职者掌握大厂面试中的核心知识点。 HashMap是基于哈希表实现的,其底层原理主要依赖于数组和链表。它提供了O(1)的平均时间复杂度进行插入、删除和查找操作。...

    Java集合专题总结:HashMap 和 HashTable 源码学习和面试总结

    Java集合专题总结:HashMap和HashTable源码学习和面试总结 本文总结了Java集合专题中的HashMap和HashTable,涵盖了它们的源码学习和面试总结。HashMap是一种基于哈希表的集合类,它的存储结构是一个数组,每个元素...

    HashMap的数据结构

    HashMap是Java编程语言中一个非常重要的数据结构,它属于集合框架的一部分,主要用于存储键值对(Key-Value)数据。HashMap在内部实现上基于哈希表,也称为散列表,它提供了一种快速查找、插入和删除数据的方法,...

    学习笔记:三数组实现的HashMap

    "学习笔记:三数组实现的HashMap"这篇博客文章可能讨论了一种非标准但有趣的HashMap实现,使用了三个数组来代替标准的哈希表结构。这里我们将深入探讨这种三数组实现HashMap的原理和可能的优势。 1. **基本概念**:...

    HashMap和HashTable的区别和不同

    ### HashMap与HashTable的区别详解 #### 引言 在Java编程中,`HashMap`与`HashTable`作为两种常用的数据结构,经常被用来存储键值对数据。尽管它们在功能上相似,但在实现细节、性能表现以及使用场景方面存在显著...

    HashMap类.rar

    通过分析源码,开发者可以深入理解哈希表的工作原理,学习如何在易语言中实现高效的数据结构,这对于提升程序性能和优化内存管理至关重要。同时,这也为自定义数据结构或实现其他哈希表相关的功能提供了基础。

    Java完整随笔(学习)

    "Java完整随笔(学习)"可能包含了一系列关于Java编程的基础到高级概念的笔记,是学习Java的好资源。以下是一些可能涵盖的重要知识点: 1. **Java基础**:这部分可能包括了Java的基本语法,如变量、数据类型、...

    Java HashMap类详解

    Java HashMap 类详解 本资源详细介绍了 Java 中的 HashMap 类,包括其实现机制、Hash 存储机制、集合存储机制等方面的知识点。 1. HashMap 和 HashSet 的关系 HashMap 和 HashSet 是 Java Collection Framework ...

    hashmap 实例

    《HashMap 实例解析与关联数据结构对比》 HashMap 是 Java 中常用的一种数据结构,属于 Java.util 包下的类,它是基于哈希表实现的。在本文中,我们将深入理解 HashMap 的实例及其工作原理,并与其他数据结构如 ...

    HASHMAP排序功能描述

    HashMap是Java编程语言中常用的集合类之一,它属于哈希表数据结构,提供key-value的存储方式,并且具有快速查询的特性。然而,HashMap本身并不保证元素的顺序,特别是当涉及到遍历或输出HashMap的内容时,顺序可能会...

    HashMap总结

    HashMap 总结 HashMap 是 Java 中的一种常用的数据结构,用于存储键值对(Key-Value)数据。下面是 HashMap 的一些特性和使用方法总结。 键(Key)的特性 1. 键可以为 null:HashMap 中的键可以为 null,这意味着...

    hashMap和hashTable的区别

    ### hashMap和hashTable的区别 #### 一、简介与基本概念 `HashMap` 和 `HashTable` 都是 Java 集合框架中非常重要的数据结构,它们都实现了 `Map` 接口,用于存储键值对。尽管它们在功能上有很多相似之处,但在...

    易语言HashMap类

    易语言HashMap类是一种在易语言编程环境中实现的高效数据结构,它主要用于存储键值对(key-value pairs),提供快速的数据存取。...通过深入学习和实践,开发者可以更好地利用HashMap类解决实际编程问题。

    HashMap_学习

    这是一套PPT,讲述的内容是Java的JDK中内置的几种常用的集合框架工具类的知识,重点讲解HashMap,因为不让上传视频,就先传个PPT试试;

Global site tag (gtag.js) - Google Analytics