JAVA小知识25:万字详解Map

2024-06-19 12:36
文章标签 java 详解 25 知识 map 万字

本文主要是介绍JAVA小知识25:万字详解Map,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、Map

1.1、双列集合与键值对

Map 是 Java 中的一个接口,它存储键值对 (key-value pairs),并且每个 (key) 只能映射到一个 (value)。键要求保持唯一性,值可以重复
在讲述List的时候我们引用过一张集合大图,还记得我们曾经说过吗?集合分为单列集合双列集合,单列集合有List与Set,但是双列集合只有Map。
在这里插入图片描述
那么什么是双列集合呢?就是一条数据同时存储了ke与values,这样两列数据。双列集合一一对应,每一个键只能找到自己对应的值。
在这里插入图片描述

1.2、Map的成员方法

Map作为一个双列集合的顶层接口,有如下成员方法,这些方法在所有的实现类中都可以使用。

方法说明
V put(K key, V value)将指定的值与该映射中的指定键关联(可选操作)。
V get(Object key)返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null
V remove(Object key)如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
boolean containsKey(Object key)检查 hashMap 中是否存在指定的 Key 对应的映射关系,则返回 true
boolean containsValue(Object value)检查 hashMap 中是否存在指定的 value 对应的映射关系,则返回 true
Set<K> keySet()返回此映射中包含的键的 Set 视图。
Collection<V> values()返回此映射中包含的值的 Collection 视图。
Set<Map.Entry<K, V>> entrySet()返回此映射中包含的映射关系的 Set 视图。
int size()返回此映射中的键值映射关系数。
void clear()从此映射中移除所有映射关系(可选操作)。
boolean isEmpty()如果此映射未包含键值映射关系,则返回 true
V putIfAbsent(K key, V value)如果指定键尚未与某个值相关联(或映射为 null),则将其与给定值相关联并返回 null;否则返回当前值。
void forEach(BiConsumer<? super K, ? super V> action)对此映射的每个键值映射关系执行给定操作,直到所有条目都被处理或该操作引发异常。

1.3、Map的实现类

  • HashMap:基于哈希表实现,键值对无序。
  • LinkedHashMap:继承自HashMap,维护插入顺序。
  • TreeMap:基于红黑树实现,键值对有序。

二、HashMap

2.1、HashMap的简介

HashMap 是 Map的一个实现类,用于存储键值对(key-value pairs)。它是基于哈希表的数据结构。在 HashMap 中,每个键都映射到一个唯一的值可以通过键来快速访问对应的值,算法时间复杂度可以达到 O(1)

2.2、HashMap的特点

  • 键值对存储:每个元素存储为键值对形式 (key-value pairs),键是唯一的,值可以重复。
  • 哈希表:HashMap 基于哈希表实现,通过计算键的哈希值来确定元素的存储位置。
  • 允许null:HashMap 允许一个 null 键和多个 null 值。
  • 无序:HashMap 中的元素没有顺序,不保证顺序恒定。
  • 不重复:key不允许重复,否则按照最后一次添加的值算(理解为修改)
  • 非线程安全:HashMap 不是线程安全的,多个线程同时访问时可能会导致数据不一致。
  • 没有索引:HashMap底层是哈希表,哈希表中有链表与红黑树,无法确定索引。

2.3、成员方法

HashMap继承自Map,所以一般常用的成员方法都是Map中的方法

方法说明
V put(K key, V value)将指定的值与该映射中的指定键关联(可选操作)。
V get(Object key)返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null
V remove(Object key)如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
boolean containsKey(Object key)检查 hashMap 中是否存在指定的 Key 对应的映射关系,则返回 true
boolean containsValue(Object value)检查 hashMap 中是否存在指定的 value 对应的映射关系,则返回 true
Set<K> keySet()返回此映射中包含的键的 Set 视图。
Collection<V> values()返回此映射中包含的值的 Collection 视图。
Set<Map.Entry<K, V>> entrySet()返回此映射中包含的映射关系的 Set 视图。
int size()返回此映射中的键值映射关系数。
void clear()从此映射中移除所有映射关系(可选操作)。
boolean isEmpty()如果此映射未包含键值映射关系,则返回 true
V putIfAbsent(K key, V value)如果指定键尚未与某个值相关联(或映射为 null),则将其与给定值相关联并返回 null;否则返回当前值。
void forEach(BiConsumer<? super K, ? super V> action)对此映射的每个键值映射关系执行给定操作,直到所有条目都被处理或该操作引发异常。
2.3.1 put:添加
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Cherry", 3);
System.out.println(map); // {Apple=1, Banana=2, Cherry=3}
2.3.2 get:获取

这里要注意,get方法只能根据键来取值

Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
Integer value = map.get("Apple");
System.out.println(value); // 1
2.3.3 remove:删除
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.remove("Banana");
System.out.println(map); // {Apple=1}
2.3.4 containsKey:是否包含该键
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
boolean hasApple = map.containsKey("Apple");
System.out.println(hasApple); // true
2.3.5 containsValue:是否包含该值
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
boolean hasValue1 = map.containsValue(1);
System.out.println(hasValue1); // true
2.3.6 keySet:获取ket的set列表(将所有key存入set集合)
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
Set<String> keys = map.keySet();
System.out.println(keys); // [Apple, Banana]
2.3.7 values:返回此映射中包含的值的 Collection集合
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
Collection<Integer> values = map.values();
System.out.println(values); // [1, 2]
2.3.8 entrySet:返回此映射中包含的映射关系的Set视图
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
System.out.println(entries); // [Apple=1, Banana=2]
2.3.9 forEach
// forEach 方法示例
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.forEach((k, v) -> System.out.println(k + ": " + v));

2.4、HashMap的遍历方式

2.4.1、第一种:for循环通过键找值
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Lemon", 3);
// 获取key
Set<String> keystr = map.keySet();
for (String s : keystr) {Integer integer = map.get(s);System.out.println(s+"="+integer);// Apple=1 Lemon=3 Banana=2
}
2.4.2、第二种:foreach
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Lemon", 3);
// 获取key
map.forEach((e,v)-> System.out.println(e+"="+v));// Apple=1 Lemon=3 Banana=2
2.4.3、第三种:迭代器通过键找值
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Lemon", 3);
Set<String> keySet = map.keySet();
Iterator<String> iterator = keySet.iterator();
while(iterator.hasNext()) {String next = iterator.next();Integer integer = map.get(next);System.out.println(next+"="+integer);// Apple=1 Lemon=3 Banana=2
}
2.4.4、第四种:通过entry对象获取或者通过entry单独获取
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Lemon", 3);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
System.out.println(entries);//[Apple=1, Lemon=3, Banana=2]
for (Map.Entry<String, Integer> entry : entries) {String key = entry.getKey();Integer value = entry.getValue();System.out.println(key+"="+value);// Apple=1 Lemon=3 Banana=2
}

2.5、HashMap的底层原理

HashMap与HashSet底层一样都是使用了哈希表 哈希表是一种对增删改查性能都良好的结构。
哈希表的组成:

  • jdk8以前:数组+链表
  • jdk8以后:数组+链表+红黑树

哈希表的灵魂是哈希值(可以理解为对象的整数表现形式),其特点如下:

  • 根据hashcode方法算出来的int类型的整数
  • 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
  • 一般情况下,会重写hashcode方法,利用对象内部的属性值计算哈希值

对象哈希值的特点:

  • 如果没有重写hashcode方法,不同对象计算出的哈希值是不同的
  • 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
  • 在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希冲突)

第一步:与HashSet一样,HashMap他的底层也会创建一个默认长度16,默认加载因子为0.75的数组
第二步:map.put的底层会创建一个Entrty对象来存放我们要存储的键值对
第三步:利用键来计算出哈希值,在根据hash值计算出数组中的索引
第四步:如果该索引为null,则直接存入数组中
第五步:如果不为null,会调用equals方法比较键的属性值,如果属性值一样,就会覆盖原有的Entrty对象,如果不一样就会添加到索引下方链表
第六步:当数组长度超过 默认长度 * 加载因子(16 * 0.75=12)的时候,数组就会扩容到之前的两倍变成新的默认长度(32);
第七步:在jdk8以后,如果链表长度超过8而且数组长度超过64,则链表会转化为红黑树;
在这里插入图片描述

三、LinkedHashMap

还是与LinkedHashSet一样,LinkedHashMap是有序地,不重复,无索引的。这里的有序指的是存和取是有顺序的。他的底层虽然还是哈希表,但是每个元素又额外的多了一个双链表的机制记录存储的顺序。
在这里插入图片描述
其成员方法可以用Map的。

这篇关于JAVA小知识25:万字详解Map的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075044

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始