容器HashMap原理(学习)

一、概述

基于哈希表Map 接口非同步实现,允许使用 null 值和 null 键,不保证映射的顺序

二、数据结构

HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体;HashMap 底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个 HashMap 的时候,就会初始化一个数组。

三、源码解读

put =>

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

get=>

在 HashMap 中要找到某个元素,需要根据 key 的 hash 值来求得对应数组中的位置。

对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 hash 码值总是相同的。我们首先想到的就是把 hash 值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。

而 HashMap 底层数组的长度总是 2 的 n 次方,这是 HashMap 在速度上的优化;

归纳:

HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据 hash 算法来决定其在数组中的存储位置,在根据 equals 方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry 时,也会根据 hash 算法找到其在数组中的存储位置,再根据 equals 方法从该位置上的链表中取出该Entry。

四、HashMap 什么时候进行扩容呢(resize)

当 HashMap 中的元素个数超过数组大小 *loadFactor时,就会进行数组扩容,loadFactor的默认值为 0.75,默认情况下,数组大小为 16,那么当 HashMap 中元素个数超过 16*0.75=12 的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知 HashMap 中元素的个数,那么预设元素的个数能够有效的提高 HashMap 的性能。

五、Fail-Fast 机制

java.util.HashMap 不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了 map,那么将抛出 ConcurrentModificationException,这就是所谓 fail-fast 策略,迭代器的快速失败行为应该仅用于检测程序错误

六、遍历方式

 效率较高的:

 Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }

效率较低的:
 Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }
foreach方式:

 for(Entry<String, String> entry:hashmap.entrySet()){        System.out.println(entry.getKey()+"-->"+entry.getValue());   }        
时间: 2024-08-09 10:36:52

容器HashMap原理(学习)的相关文章

docker容器网络通信原理分析

概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两方面,对容器的通信原理进行简单的分析,帮助大家更好地使用docker. docker单主机容器通信 基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以

IoC容器实现原理

实例化 在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中. 依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. IoC容器工作原理 大致分为BeanDefinition的定位.IoC容器初始化.依赖注入三个过程,具体说明如下: BeanDefinition的定位.对IoC容器来说,它为管理POJO之间的依赖关系提供了帮助,但

spring容器IOC原理解析

原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean.下面是一段简单的模拟代码: [java] view plain copy package com.tgb.spring.factory; import java.util.HashMap; import java.util.List; import java.util.Map; import or

Android自复制传播APP原理学习(翻译)

 Android自复制传播APP原理学习(翻译) 1 背景介绍 论文链接:http://arxiv.org/abs/1511.00444 项目地址:https://github.com/Tribler/self-compile-Android 吃完晚饭偶然看到这篇论文,当时就被吸引了,马上翻译总结了一下.如有错误欢迎斧正. 该论文的研究出发点比较高大上这里我们就不多说了,简而言之就是想通过移动设备来实现一个自组网,在发生灾难的时候,手机之间能够自动传输关键数据,减少损失.整个目标通过设计一个能够

编译原理学习导论

编译原理学习导论 大学课程为什么要开设编译原理呢?这门课程关注的是编译器方面的产生原理和技术问题,似乎和计算机的基础领域不沾边,但是编译原理却一直作为大学本科的必修课程,同一时候也成为了研究生入学考试的必考内容.编译原理及技术从本质上来讲就是一个算法问题而已,当然因为这个问题十分复杂,其解决算法也相对复杂.我们学的数据结构与算法分析也是讲算法的,只是讲的基础算法,换句话说讲的是算法导论,而编译原理这门课程讲的就是比較专注解决一种的算法了.在20世纪50年代,编译器的编写一直被觉得是十分困难的事情

编译原理学习笔记 -- 绪论1

1. 语言处理器 语言处理系统 _________ 经过预 _______ 源程序 --> |预处理器| --> 处理的 --> |编译器| --> 目标汇编程序 -------- 源程序 ------- _______ 可重定位的 ______________ --> |汇编器| --> 机器代码 --> |链接器/加载器| --> 目标机器代码 ------- -------------- ↑ 库文件/可重定位对象文件 预处理器:把源程序聚合在一起,并宏

计算机原理学习(7)-- x86-32 CPU和内存管理之分段管理

前言 前一篇我们介绍了内存管理中的分页试内存管理,分页的主要作用就是使得每个进程有一个独立的,完整的内存空间,通过虚拟内存技术,使得程序可以在较小的内存上运行,而进程之间内存空间相互独立,提高了安全性.这一篇将主要介绍内存管理中分段管理,以及两种的结合,也是目前计算机普遍采用的段页式内存管理.这也直接决定了的后面程序的编译,加载以及允许时的内存布局. 1. 内存分段 1.1 为什么分段? 在x86-16体系中,为了解决16位寄存器对20位地址线的寻址问题,引入了分段式内存管理.而CPU则使用CS

MapDemo1+2 Map接口的常用方法及遍历 及HashMap原理

MapDemo1 Map接口的常用方法 /** * java.util * Map接口<K,V> 类型参数: K - 此映射所维护的键的类型 V - 映射值的类型 定义: Map是一个接口,又称作查找表 java提供了一组可以以键值对(key-value)的形式存储数据的数据结构, 这种数据结构成为Map.我们可以看成是一个多行两列的表格,一列是存放key,一列存放value. 而每一行就相当于一组 key-value对,表示一组数据. 注意: 1.Map对存入元素有一个要求,就是key不能重

编译原理学习

编译原理学习笔记---- 不确定有穷自动机(NFA) 一个不确定的有穷自动机T是一个五元组,M={K,∑,f,S,Z} ⒈K是一个有穷集他的每一个元素称作一个状态. ⒉∑是一个字母表,他的每一个元素称为一个输入符号. ⒊f是一个从Kx∑*到K的子集映射即K*∑*->2^K,其中2^K表示K的幂集. ⒋S包含于K集,是一个非空初态集合. ⒌Z包含于K是一个非空的终态集合. 确定有穷自动机(DFA) 一个确定的有穷自动机M是一个五元组:M=(K, ∑,f,S,Z)其中, 1)K是一个有穷集,他的每个