Java集合框架(四)-HashMap
1、HashMap特点
| 存放的元素都是键值对(key-value),key是唯一的,value是可以重复的 |
|---|
| 存放的元素也不保证添加的顺序,即是无序的 |
| 存放的元素的键可以为null,但是只能有一个key为null,可以有多个value为null(前提是存放的是HasHap对象) |
| 如果新添加的元素的键(key)在集合中已经存在,自动将新添加的值覆盖到原有的值 |
2、底层实现
HashMap的底层使用的是Node对象数组;
HashMap源码
transient Node<K,V>[] table; //Node对象数组
//Node类
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
......
}
3、扩容
- HashMap的底层使用的是Node对象数组,初始容量(未自定义)是16,根据负载因子跟数组容量,计算出扩容临界值,每当存放元素达到了临界值就可以扩容,而不是等到数组长度不够;
- 每次扩容,都是原有数组容量的2倍,必须要保证是2的整数次幂(底层算法实现),最大容量是2的30次方;
初始容量和默认扩容因子
/**
* Constructs an empty <tt>HashMap</tt> with the default initial capacity
* (16) and the default load factor (0.75).
*/
//初始容量为16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//默认扩容因子为0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//最大容量是2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
4、初始化
Map<String,String> carMap = new HashMap<>(); //推荐使用
5、常用方法
| put(key, value) | 添加键值对 |
|---|---|
| get(Object key) | 通过key获取value |
| size() | 获取集合键值对数量 |
| keySet() | 获取所有的键集合(返回值为set集合) |
| values() | 获取所有值集合 |
| containsKey(Object key) | 判断某个键是否存在 |
| containsValue(Object value) | 判断某个值是否存在某个值 |
| remove(Object key) | 根据键值删除键值对 |
| clear() | 清空集合 |
5.1 put(key, value);
添加键值对方法;
可以添加 null 的key 或者value,键只能由一个null,值可以由多个null;
5.2 get(Object key)
获取键值对的方法:get(key),只能根据key获取value,如果key不存在,不会报错,返回null;
5.3 size()
获取集合中存放键值对数量;
5.4 keySet()
获取所有的键集合;
Map<String,String> carMap = new HashMap<>();
carMap.put("Audi","奥迪");
carMap.put("Benz","奔驰");
carMap.put("Bmw","宝马");
Set<String> keySet = carMap.keySet();
System.out.println("获取所有的键集合:"+keySet);//[Benz, Audi, Bmw]
5.5 values()
获取所有值集合方法;
Collection<String> values = carMap.values();
System.out.println(values);//[奔驰, 奥迪, 宝马]
5.6 containsKey(Object key)
判断集合中是否包含某个键值对,存在返回true;
5.7 containsValue(Object value)
判断集合中是否包含某个值,不可以作为键值对的唯一标识,值可重复;
5.8 remove(Object key)
删除键值对方法;
5.9 clear()
清空map集合;
6、遍历
6.1 方式一:迭代器(不可以通过map集合直接获取,因为它只能通过Collection获取)
System.out.println("方式一");
Iterator<String> iterator = carKeySet.iterator();
while (iterator.hasNext()){
//获取key
String carKey = iterator.next();
//根据key 获取值
String carValue = carMap.get(carKey);
System.out.print(carKey + "---" + carValue +" ");
}
6.2 方式二:增强for,原理和上一个类似,也根据键的集合,获取值
System.out.println("\n"+"方式二");
for (String carKey : carMap.keySet()) {
System.out.print(carKey+"---"+carMap.get(carKey)+" ");
}
6.3 方式三:增强for,操作的是Map.Entry对象,推荐写法,效率较高
System.out.println("\n"+"方式三");
for (Map.Entry<String,String> entry : carMap.entrySet()){
System.out.print(entry.getKey()+"---"+entry.getValue()+" ");
}
运行结果
Benz---奔驰 Audi---奥迪 Bmw---宝马
7、TreeMap
自带排序功能的集合map,TreeMap,自动按照key的字典序排序;
System.out.println("自带排序功能的集合map,TreeMap,自动按照key的字典序排序");
Map<String,String> paramsMap = new TreeMap<>();
paramsMap.put("body","TreeMap");
paramsMap.put("userId","U0001");
paramsMap.put("sign","sign");
paramsMap.put("appId","KH96");
System.out.println(paramsMap);
自带排序功能的集合map,TreeMap,自动按照key的字典序排序
{appId=KH96, body=TreeMap, sign=sign, userId=U0001}
8、HashTable
Hashtable,是map集合的实现类,但是跟HashMap的去表是,线程安全的;
Hashtable的put方法源码
//put方法是同步安全的
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
默认初始容量是11,扩容因子也是0.75;
Hashtable初始化源码
/**
* Constructs a new, empty hashtable with a default initial capacity (11)
* and load factor (0.75).
*/
//默认初始容量是11
//扩容因子也是0.75
public Hashtable() {
this(11, 0.75f);
}
每次扩容是之前容量的2倍+1;
Hashtable扩容源码
protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table;
// 新数组的容量=旧数组长度*2+1
int newCapacity = (oldCapacity << 1) + 1;
// 保证新数组的大小永远小于等于MAX_ARRAY_SIZE
// MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
return;
newCapacity = MAX_ARRAY_SIZE;
}
// 创建新数组
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
modCount++;
// 计算新的临界值
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;
// 将旧数组中的元素迁移到新数组中
for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;
//计算新数组下标
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
// 头插法的方式迁移旧数组的元素
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
Java集合框架(四)-HashMap的更多相关文章
- Java集合框架之HashMap浅析
Java集合框架之HashMap浅析 一.HashMap综述: 1.1.HashMap概述 位于java.util包下的HashMap是Java集合框架的重要成员,它在jdk1.8中定义如下: pub ...
- Java集合框架:HashMap
转载: Java集合框架:HashMap Java集合框架概述 Java集合框架无论是在工作.学习.面试中都会经常涉及到,相信各位也并不陌生,其强大也不用多说,博主最近翻阅java集合框架的源码以 ...
- (转)Java集合框架:HashMap
来源:朱小厮 链接:http://blog.csdn.net/u013256816/article/details/50912762 Java集合框架概述 Java集合框架无论是在工作.学习.面试中都 ...
- Java集合框架(四)
Collections 集合框架的工具类 着重讲解以下方法: 1.sort(): 1º根据元素的自然顺序对指定列表按升序进行排序,列表中的所有元素都必须实现comparable接口. pu ...
- Java 集合框架:HashMap
原文出处:Java8 系列之重新认识 HashMap 摘要 HashMap 是 Java 程序员使用频率最高的用于映射 (键值对) 处理的数据类型.随着 JDK(Java Developmet Kit ...
- java集合框架之HashMap
参考http://how2j.cn/k/collection/collection-hashmap/365.html#nowhere HashMap的键值对 HashMap储存数据的方式是-- 键值对 ...
- java集合框架之HashMap和Hashtable的区别
参考http://how2j.cn/k/collection/collection-hashmap-vs-hashtable/692.html#nowhere HashMap和Hashtable的区别 ...
- java 集合框架(四)Set
一.概述 Set是一种没有重复元素的集合,它所有的方法都是直接继承自Collection接口,并且添加了一个对重复元素的限制.Set要求强化了equals和hashCode两个方法,以使Set集合可以 ...
- 深入理解java集合框架之---------HashMap集合
深入理解HaspMap死循环问题 由于在公司项目中偶尔会遇到HashMap死循环造成CPU100%,重启后问题消失,隔一段时间又会反复出现.今天在这里来仔细剖析下多线程情况下HashMap所带来的问题 ...
随机推荐
- Spring配置文件-Bean实例化的三种方式
1.无参构造方法实例化(详见我的博客) 2.工厂静态方法实例化 创建StaticFactory类 public class StaticFactory { public static UserDao ...
- 约定编程与Sping AOP
一.约定编程 Spring AOP是一种约定流程的编程,咱们可以先通过动态代理模式的实现来理解Spring AOP的概念. 代理的逻辑很简单,例如,当你需要采访一名儿童时,首先需要经过他父母的同意,在 ...
- 控制Python浮点数输出位数
技术背景 在Python的一些长效任务中,不可避免的需要向文本文件.二进制文件或者数据库中写入一些数据,或者是在屏幕上输出一些文本,此时如何控制输出数据的长度是需要我们注意的一个问题.比如对于一个二进 ...
- Java指令重排序在多线程环境下的应对策略
一.序言 指令重排在单线程环境下有利于提高程序的执行效率,不会对程序产生负面影响:在多线程环境下,指令重排会给程序带来意想不到的错误. 本文对多线程指令重排问题进行复原,并针对指令重排给出相应的解决方 ...
- Metalama简介4.使用Fabric操作项目或命名空间
使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题 Metalama简介1. 不止是一个.NET跨平台的编译时AOP框架 Metalama简介2.利用Aspect在编译时进行消除重 ...
- GO语言学习——运算符
运算符 Go 语言内置的运算符有: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 算术运算符 运算符 描述 + 相加 - 相减 * 相乘 / 相除 % 求余 注意: ++(自增)和--(自 ...
- 《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
1.简介 上一篇宏哥用PageFactory实现了POM,宏哥再介绍一下如果不用PageFactory如何实现POM. 2.项目实战 在这里宏哥以百度首页登录的例子,如果用POM实现,在测试脚本中实际 ...
- 4 个超实用的 Linux 监控工具
公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 下面是 Linux 下 4 个日常使用率非常高的监控工具,可以帮助我们准确快速的诊断系统问题. 1. iotop 如果你想知 ...
- WSL与Windows环境共享
Reference 更多cmd.exe帮助参考 cmd_helps WSL备份及windows Docker安装 WSL安装维护 在使用wsl时,总是需要执行windows的cmd,但是windows ...
- Nvidia Triton使用教程:从青铜到王者
1 相关预备知识 模型:包含了大量参数的一个网络(参数+结构),体积10MB-10GB不等 模型格式:相同的模型可以有不同的存储格式(可类比音视频文件),目前主流有torch.tf.onnx和trt, ...