Java Map 源码解析:核心原理与应用
Java Map 源码解析:核心原理与应用
Java 的 Map
接口是集合框架中一个重要的组成部分,专门用于存储键值对。其强大的功能和灵活的实现使其在各种应用场景中得到了广泛的使用。本文面向对 Java 集合框架有一定了解的开发者,通过对 Map
接口及其常见实现类的源码解析,帮助深入理解其核心原理和应用。
一、背景与简介
Map
接口在 Java 集合框架中承担着键值对存储和快速检索的职责。它提供了一种通过键(Key)唯一标识值(Value)的存储方式。
1.1 Map 的特点
- 键值对存储:每个键对应一个唯一的值。
- 键的唯一性:相同键的插入会覆盖旧值。
- 线程安全问题:大多数实现类(如
HashMap
)非线程安全,需根据场景选择适合的实现。
1.2 常见实现类及适用场景
HashMap
:基于哈希表实现,无序存储,适合快速查找的场景。TreeMap
:基于红黑树实现,有序存储,适合需要排序的场景。LinkedHashMap
:维护插入顺序或访问顺序。ConcurrentHashMap
:线程安全,适合并发环境。
示例代码:
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 30);
map.put("Bob", 25);
System.out.println(map.get("Alice")); // 输出 30
二、Map 接口解析
Map
接口定义了许多核心方法,其设计直接影响了实际操作的性能和可用性。
2.1 核心方法
put(K key, V value)
:添加或更新键值对。get(Object key)
:根据键获取值。containsKey(Object key)
:检查是否包含某键。entrySet()
、keySet()
和values()
:提供视图方法以便操作键值对。
示例代码:
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 30);
map.put("Bob", 25);
System.out.println(map.containsKey("Alice")); // 输出 true
System.out.println(map.entrySet()); // 输出所有的键值对
2.2 默认方法
Java 8 引入了默认方法,例如:
forEach
:遍历键值对。getOrDefault
:获取值时指定默认值。
示例代码:
map.forEach((key, value) -> System.out.println(key + ": " + value));
System.out.println(map.getOrDefault("Charlie", 0));
三、常见实现类源码剖析
3.1 HashMap 源码剖析
```tex
HashMap 源码put 过程 涉及面试 如果解决hash冲突hash = hash(key);index = hash & *(table.length -1)树化的阈值 8 考虑树化数组的长度未到达64 --> 扩容 为原来的2倍数组的长度到达64 --> 树化反树化 阈值 6 考虑反树化反树化的情况1> 父节点的左子节点或右子节点 为null2> 父节点的左子树的左节点为null扩容时机1> 链表长度>8 + 数组的长度未到达64 --> 扩容为原来的2倍2> size 达到了 扩容阈值 (table.length * 加载因子) --> 扩容为原来的2倍Map集合在使用时,键只推荐使用String 以及包装类
``````java
package com.atguigu.test;import java.util.HashMap;public class Demo10_HashMap_JDK8 {/*HashMap 源码put 过程 涉及面试 如果解决hash冲突hash = hash(key);index = hash & *(table.length -1)树化的阈值 8 考虑树化数组的长度未到达64 --> 扩容 为原来的2倍数组的长度到达64 --> 树化反树化 阈值 6 考虑反树化反树化的情况1> 父节点的左子节点或右子节点 为null2> 父节点的左子树的左节点为null扩容时机1> 链表长度>8 + 数组的长度未到达64 --> 扩容为原来的2倍2> size 达到了 扩容阈值 (table.length * 加载因子) --> 扩容为原来的2倍Map集合在使用时,键只推荐使用String 以及包装类*/public static void main(String[] args) {HashMap<MyKey,Integer> map = new HashMap<>();for (int i = 0; i < 100; i++) {map.put(new MyKey(i),i);}System.out.println(map);}
}```
数据结构
HashMap
基于 数组 + 链表/红黑树 实现:
- 使用数组存储键值对。
- 处理哈希冲突时,链表长度超过阈值(默认 8)后转换为红黑树。
核心方法解析
put
方法- 计算键的哈希值。
- 根据哈希值找到对应的桶。
- 如果桶中存在相同键,更新值;否则插入新节点。
简化代码:
public V put(K key, V value) {int hash = hash(key);int index = (n - 1) & hash; // 计算桶索引if (table[index] == null) {table[index] = new Node<>(hash, key, value, null);} else {// 处理哈希冲突...}return oldValue;
}
get
方法- 根据键计算哈希值,找到对应的桶。
- 遍历桶中的节点,查找匹配的键。
性能优化
- 哈希函数减少冲突。
- 链表转红黑树优化查询效率。
```java
// JDK1.7
private class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默认的初始化容量 16static final float DEFAULT_LOAD_FACTOR = 0.75f;// 默认加载因子 0.75Fstatic final int TREEIFY_THRESHOLD = 8;static final int UNTREEIFY_THRESHOLD = 6;static final int MIN_TREEIFY_CAPACITY = 64;public HashMap() {//DEFAULT_INITIAL_CAPACITY:默认的初始化容量 16//DEFAULT_LOAD_FACTOR:默认加载因子 0.75Fthis(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);//调用本类的其他构造器}public V put(K key, V value) {//table是数组,存储键值对的数组,元素的类型Entry类型。//如果HashMap还没有添加过元素,table就是一个空数组if (table == EMPTY_TABLE) {inflateTable(threshold);//阈值 = 16; 阈值初始化为16//如果数组是空数组,长度变为16,threshold = capacity * loadFactor = 16 * 0.75 = 12}//HashMap允许key为null,Hashtable不允许if (key == null)//如果key为null,特殊处理return putForNullKey(value);// key为null的键值对,一定是存储在table[0]下面的。//计算key的hash值int hash = hash(key);//计算新的映射关系的存储下标table[i] ,依据为:key的hash值和数组的长度int i = indexFor(hash, table.length);//先取出table[i]的头结点//如果头结点不满足,就依次判断下面的结点 e = e.nextfor (Entry<K, V> e = table[i]; e != null; e = e.next) {Object k;//如果e.hash == hash 并且 要么是e.key 和新的映射关系的key地址相同或equls相同//说明e的key与新的映射关系的key相同if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//用新的value覆盖原来的valueV oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}modCount++;//添加新的映射关系到table[i]的位置,作为table[i]的头结点,原来table[i]下面的链表连接到它next中addEntry(hash, key, value, i);return null;}private void inflateTable(int toSize) {// Find a power of 2 >= toSize//如果数组的长度不是2的n次方,纠正为2的n次方int capacity = roundUpToPowerOf2(toSize);//重新计算阈值 = capacity * loadFactor;threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);//table重新建新数组 ,长度为 capacitytable = new Entry[capacity];//暂时不管它,hash种子有关initHashSeedAsNeeded(capacity);}private V putForNullKey(V value) {//整个for循环的作用://(1)先取出数组table[0]的第一个元素e,如果e不为null//(2)判断e的key是否为null,如果e.key为null,就用新的value覆盖原来的value//(3)e=e.next,继续判断下一个结点//所有的操作都是在table[0]下面的//key为null的键值对,一定是存储在table[0]下面的。for (Entry<K, V> e = table[0]; e != null; e = e.next) {if (e.key == null) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}modCount++;//把新的键值对(null,value)存储到table[0]的下面addEntry(0, null, value, 0);//hash=0,key=null,value=value,bucketIndex=0return null;}void addEntry(int hash, K key, V value, int bucketIndex) {//size:HashMap中所有键值对的个数//size >= threshold,达到阈值 并且 table[bucketIndex]非空//同时满足它俩的话,就会扩容if ((size >= threshold) && (null != table[bucketIndex])) {resize(2 * table.length);//把数组table扩大为原来的2倍hash = (null != key) ? hash(key) : 0; //重写计算key的hash值bucketIndex = indexFor(hash, table.length);//重新计算[bucketIndex]/*为什么数组扩容后,要重新计算下标?index = hash & table.length-1; 如果table.length变了,就需要重新计算 [index]*/}createEntry(hash, key, value, bucketIndex);}//本来我们想着直接使用key的hashCode()计算的结果的,但是很多时候用户自己实现的hashCode()不是很好//冲突现象比较严重,所以他在hashCode()的基础上做了一些干扰的操作,使得hash值更分散。//如果hash值更分散,那么存储到table中就会更均匀分布,而不是都在某个table[index]final int hash(Object k) {int h = hashSeed;if (0 != h && k instanceof String) {return sun.misc.Hashing.stringHash32((String) k);}h ^= k.hashCode();// This function ensures that hashCodes that differ only by// constant multiples at each bit position have a bounded// number of collisions (approximately 8 at default load factor).h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);}void createEntry(int hash, K key, V value, int bucketIndex) {//取出[bucketIndex]位置的元素,即table[bucketIndex]的头结点Entry<K, V> e = table[bucketIndex];//table[bucketIndex]的头结点变为新结点(key,value)的Entry对象。//原来table[bucketIndex]下面的链表作为新结点的nexttable[bucketIndex] = new Entry<>(hash, key, value, e);//元素个数增加size++;}//HashMaP的元素类型,类似于我们在LinkedList中看到都Node,只是另一种形式的结点static class Entry<K, V> implements Map.Entry<K, V> {final K key;V value;Entry<K, V> next;int hash;/*** Creates new entry.*/Entry(int h, K k, V v, Entry<K, V> n) {value = v;next = n;key = k;hash = h;}}// 用key的hash值 & 和数组的长度-1,计算下标static int indexFor(int h, int length) {// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";//用key的hash值, 和数组的长度-1做运算得到下标,范围[0,table.length-1]范围内return h & (length - 1);}
}
```1、put(key,value)(1)当第一次添加映射关系时,数组初始化为一个长度为**16**的**HashMap$Entry**的数组,这个HashMap$Entry类型是实现了java.util.**Map.Entry**接口(2)特殊考虑:如果key为null,index直接是[0],hash也是0(3)如果key不为null,在计算index之前,会对key的hashCode()值,做一个hash(key)再次哈希的运算,这样可以使得Entry对象更加散列的存储到table中(4)计算index = table.length-1 & hash;(5)如果table[index]下面,已经有映射关系的key与我要添加的新的映射关系的key相同了,会用新的value替换旧的value。(6)如果没有相同的,会把新的映射关系添加到链表的头,原来table[index]下面的Entry对象连接到新的映射关系的next中。(7)添加之前先判断if(size >= threshold && table[index]!=null)如果该条件为true,会扩容```java
if(size >= threshold && table[index]!=null){①会扩容②会重新计算key的hash③会重新计算index}
```
3.2 TreeMap 源码剖析
数据结构
TreeMap
基于 红黑树 实现,具有以下特点:
- 键值对按键的自然顺序或指定的比较器排序。
- 支持高效的范围查询。
核心方法解析
- 插入
- 将新节点插入到红黑树中。
- 维护红黑树的平衡性。
- 查询
- 利用红黑树的特性,查询复杂度为 O(log n)。
示例代码:
TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Alice", 30);
treeMap.put("Bob", 25);
System.out.println(treeMap);
四、性能与使用场景分析
4.1 性能对比
实现类 | 数据结构 | 时间复杂度 | 适用场景 |
---|---|---|---|
HashMap | 数组 + 链表/红黑树 | O(1)(查找、插入) | 快速查找,无需排序的场景。 |
TreeMap | 红黑树 | O(log n)(查找、插入) | 需要有序存储的场景。 |
ConcurrentHashMap | 分段锁 | O(1)(查找、插入) | 并发访问。 |
LinkedHashMap | 哈希表 + 双向链表 | O(1)(查找、插入) | 保留插入顺序或访问顺序的场景。 |
4.2 使用建议
- 普通场景:
HashMap
是首选。 - 有序存储:使用
TreeMap
。 - 线程安全:使用
ConcurrentHashMap
。 - 顺序敏感:使用
LinkedHashMap
。
五、总结与延伸阅读
5.1 总结
Map
接口及其实现类在 Java 开发中扮演重要角色。从 HashMap
的高效性到 TreeMap
的有序性,以及 ConcurrentHashMap
的线程安全特性,不同的实现类满足了不同的场景需求。
5.2 延伸阅读
- JDK 官方文档
- 《Java 并发编程实战》
- 《深入理解 Java 虚拟机》
六、实践案例
案例:统计用户访问页面次数
在一个网站中,我们需要统计每个用户访问某些页面的次数,并能够动态地增加访问记录。使用 HashMap
可以非常高效地完成这一任务。
import java.util.HashMap;
import java.util.Map;public class UserPageVisitCounter {// 用于存储每个用户的页面访问记录private final Map<String, Map<String, Integer>> userVisitMap = new HashMap<>();/*** 记录用户对页面的访问* @param userId 用户 ID* @param page 页面名称*/public void recordVisit(String userId, String page) {// 获取当前用户的访问记录Map<String, Integer> pageVisitCount = userVisitMap.getOrDefault(userId, new HashMap<>());// 更新用户对当前页面的访问次数pageVisitCount.put(page, pageVisitCount.getOrDefault(page, 0) + 1);// 更新总表中的记录userVisitMap.put(userId, pageVisitCount);}/*** 获取用户对某页面的访问次数* @param userId 用户 ID* @param page 页面名称* @return 访问次数*/public int getPageVisitCount(String userId, String page) {return userVisitMap.getOrDefault(userId, new HashMap<>()).getOrDefault(page, 0);}/*** 打印所有用户的访问统计*/public void printAllVisits() {for (Map.Entry<String, Map<String, Integer>> userEntry : userVisitMap.entrySet()) {String userId = userEntry.getKey();Map<String, Integer> visits = userEntry.getValue();System.out.println("用户 " + userId + " 的访问记录:");for (Map.Entry<String, Integer> visitEntry : visits.entrySet()) {System.out.println(" 页面:" + visitEntry.getKey() + ",访问次数:" + visitEntry.getValue());}}}public static void main(String[] args) {UserPageVisitCounter counter = new UserPageVisitCounter();// 模拟用户访问counter.recordVisit("user1", "home");counter.recordVisit("user1", "home");counter.recordVisit("user1", "about");counter.recordVisit("user2", "home");counter.recordVisit("user2", "contact");// 获取访问统计System.out.println("user1 访问 home 页面次数:" + counter.getPageVisitCount("user1", "home"));System.out.println("user2 访问 contact 页面次数:" + counter.getPageVisitCount("user2", "contact"));// 打印所有用户的访问记录counter.printAllVisits();}
}
相关文章:
Java Map 源码解析:核心原理与应用
Java Map 源码解析:核心原理与应用 Java 的 Map 接口是集合框架中一个重要的组成部分,专门用于存储键值对。其强大的功能和灵活的实现使其在各种应用场景中得到了广泛的使用。本文面向对 Java 集合框架有一定了解的开发者,通过对 Map 接口及…...
基于Mosquito源码理解MQTT5.0的属性概念
MQTT 5.0协议相比之前的版本(如MQTT 3.1.1)增加了很多属性,这些属性分布于报文的可变头部(Variable Header)和有效载荷(Payload)中。这些属性大大增强了协议的可扩展性和灵活性,使其能够更好地适应现代物联网应用的复杂需求。 属性的定义在源码包mosquitto-2.0.18/inc…...
easyui textbox使用placeholder无效
easyui textbox使用placeholder无效 在easyui 的textbox控件,请使用data-options 设定 示例 <input type text class easyui-textbox data-options "prompt:请输入您的邮箱"/>...
java AQS
什么是AQS AQS(AbstractQueuedSynchronizer,抽象队列同步器)是 Java 中并发控制的一种机制,位于 java.util.concurrent.locks 包下,它为构建锁、信号量等同步工具提供了一个框架。AQS 通过 队列 来管理多个线程之间的…...
机器人对物体重定向操作的发展简述
物体重定向操作的发展简述 前言1、手内重定向和外部重定向2、重定向原语3、重定向状态转换网络4、连续任意姿态的重定向5、利用其他环境约束重定向总结Reference 前言 对于一些特殊的任务(如装配和打包),对物体放置的位姿由明确的要求&#…...
数据结构与算法之动态规划: LeetCode 72. 编辑距离 (Ts版)
编辑距离 https://leetcode.cn/problems/edit-distance/description/ 描述 给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符 示例 1 输入&…...
vue3 Teleport瞬移组件
Teleport是瞬移组件,也称为传送门组件 它是一个可以使元素从一个组件转到另一个组件的组件。 如对话框、自定义菜单、警告提示、徽章,以及许多其他需要出现在特殊位置的自定义UI组件。假设现在页面中有两个元素,分别为div元素和button按钮元…...
Go语言学习路线
以下是一个较为系统的Go语言学习路线: 一、基础阶段 环境搭建与工具链熟悉 安装Go语言开发环境。在Go官方网站(https://golang.org/dl/)下载适合您操作系统的安装包并完成安装。 配置Go环境变量,如GOPATH和GOROOT。GOROOT是Go语…...
摄像头监视脚本
摄像头监视脚本,若检测到摄像头画面有变化,保存这一段视频 一、使用方法 1.运行脚本 默认参数Threshold3, Period3, path./recordings python cam.py --threshold30 --period3 --path./recordings 2.参数说明 threshold:摄像头捕获到的画面变化量阈值…...
【Leecode】Leecode刷题之路第97天之交错字符串
题目出处 97-交错字符串-题目出处 题目描述 个人解法 思路: todo代码示例:(Java) todo复杂度分析 todo官方解法 97-交错字符串-官方解法 方法1:动态规划 思路: class Solution {public boolean isInte…...
MAC环境安装(卸载)软件
MAC环境安装(卸载)软件 jdknode安装node,并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净,可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…...
Spring Boot + Redisson 封装分布式锁
目标:一行代码调用,简单粗暴。 基操:自动加锁,自动解锁,自动处理异常,自动处理锁超时等。 安装 redis redisson <dependency><groupId>org.springframework.boot</groupId><artifac…...
从零开发一套UWB定位系统需要多长时间?UWB超宽带定位系统源码
从零开发一套UWB定位系统需要多长时间? 从零开发一套UWB定位系统所需的时间会受到多种因素的影响,以下是详细分析: 一、系统复杂度 1、基本功能定位系统 如果只是开发一个简单的UWB定位系统,仅实现基本的定位功能,如在…...
DataCap 2024.4.1 版本发布:MongoDB 驱动支持、工作流引擎升级
尊敬的 DataCap 用户: DataCap 2024.4.1 版本现已正式发布。本次更新包含多项重要功能升级和性能优化,现将主要更新内容公布如下: 核心功能升级 数据库功能增强 (实现功能) 新增数据库管理功能:支持创建、删除和切换数据库完善表…...
常见端口(22、25、53、80、443、110、143、3306、6379、21)和服务的安装与配置手册
文章目录 一、系统初始设置1. 系统与工具的基础配置1.1 系统更新1.2 网络连接测试1.3 工具安装 2. 防火墙配置2.1 启用防火墙服务2.2 检查默认规则2.3 开放常用端口2.4 查看已开放端口 二、常见端口及其用途1. 端口 22(SSH)2. 端口 25(SMTP&a…...
使用maven-mvnd替换maven大大提升编译打包速度
先上结论!!! 多模块清理并打包提升:约3.5倍 多模块不清理打包提升:约5.5倍 单模块提升:约2倍 从计算结果来看,多模块提升的效率更高。在使用mvnd package打包多模块式,可在控制台…...
图像去雾 | 基于Matlab的图像去雾系统(四种方法)
图像去雾 | 基于Matlab的图像去雾系统(四种方法) 目录 图像去雾 | 基于Matlab的图像去雾系统(四种方法)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于Matlab的图像去雾系统(四种方法) 关于图像…...
【Ubuntu 系统 之 开启远程桌面SSH登录】
【Ubuntu 系统 之 开启远程桌面&SSH登录】 一、开启 SSH 登录二、开启远程桌面1、更新包管理器并安装 xrdp1.1、遇到错误1.2、解决方法 2、安装桌面环境(如果服务器上没有 GUI)3、配置 xrdp 使用默认的 GNOME 桌面环境4、配置防火墙允许远程桌面连接…...
利用 AI 生成 XMind 思维导图教程
本文将介绍如何使用 AI 工具(如 ChatGPT 等),从无到有生成层次分明、可直接导入到 XMind 的 Markdown 格式思维导图。主要步骤包括:选择主题、编写并润色 Markdown 文档、在 XMind 中进行导入与可视化。 一、为什么使用 AI XMind…...
电子应用设计方案81:智能AI冲奶瓶系统设计
智能 AI 冲奶瓶系统设计 一、引言 智能 AI 冲奶瓶系统旨在为父母或照顾者提供便捷、准确和卫生的冲奶服务,特别是在夜间或忙碌时,减轻负担并确保婴儿获得适宜的营养。 二、系统概述 1. 系统目标 - 精确调配奶粉和水的比例,满足不同年龄段婴…...
MySQL的索引
没有索引会怎么样 数据库中的数据最终是存储在磁盘上的。 mysql服务器,本质上是内存进程,CURD操作全都是在内存中进行的—索引也是如此。 所以,需要将数据从磁盘读进内存,才能进行操作。 如果没有索引,表中的数据会向…...
Pytest 高级用法:间接参数化
文章目录 1. 引言2. 基础概念2.1 Fixture2.2 参数化 3. 代码实例3.1 基础设置3.2 测试用例示例示例 1:基础的间接参数化示例 2:通过 request 获取参数值示例 3:多参数组合测试示例 4:部分间接参数化 4. 最佳实践5. 总结参考资料 1…...
基于视觉语言模型(VLM)的CogAgent
前言 CogAgent 是由清华大学与智谱AI联合推出的一个多模态大模型,专注于图形用户界面(GUI)的理解和导航。它代表了在视觉语言模型(VLM)领域的一项重要进展,特别是在GUI Agent能力方面。相较于传统的基于文…...
文件传输工具FTransferor<优化篇>
在上一篇文章中,我们详细探讨了FTransferor文件传输工具的设计与实现,并展示了它在局域网文件传输方面的高效性。然而,随着互联网应用场景的不断丰富,传统的基于 TCP/UDP 的传输方式已经无法满足部分开发者的需求。特别是在跨平台…...
【Linux】Centos7下载npm
Index of /dist/v16.20.2/ (nodejs.org) 下载 wget https://nodejs.org/dist/v16.20.2/node-v16.20.2-linux-x64.tar.gz解压 sudo tar -zxvf node-v16.20.2-linux-x64.tar.gz 配置环境变量 sudo vim /etc/profile export NODE_HOME/usr/local/node-v16.20.2-linux-x64 ex…...
Spring boot + Hibernate + MySQL实现用户管理示例
安装MySQL Windows 11 Mysql 安装及常用命令_windows11 mysql-CSDN博客 整体目录 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLS…...
Neo4j GDS 2.0 安装与配置
Neo4j GDS 2.0 安装与配置 GDS插件安装:Neo4j官方文档 1. GDS简介 Neo4j Graph Data Science (GDS) 库作为 Neo4j Graph Database 的插件提供。该插件需要安装到数据库中并在 Neo4j 配置中列入白名单。有两种主要方法可以实现这一点,我们将在本章中详…...
【非关系型数据库Redis 】 入门
Redis入门 一、非关系型数据库概述 (一)概念 非关系型数据库(NoSQL,Not Only SQL)是相对于传统的关系型数据库而言的一种数据存储管理系统。它摒弃了关系型数据库中严格的表结构、SQL 语言操作以及复杂的事务等特性…...
【Linux报告】实训一:GNME桌面环境的设置及应用
实训一:GNME桌面环境的设置及应用 【练习1】在图形模式和文本模式下登录Linux系统。 1、开启Linux虚拟机。 答:打开此虚拟机如图所示 2、观察屏幕上显示的启动信息。 3、当系统启动到图形界面时,用普通用户身份登录。 答:如图…...
mysql8 从C++源码角度看 客户端发送的sql信息 mysql服务端从网络读取到buff缓存中
MySQL 8 版本中的客户端-服务器通信相关,特别是在接收和解析网络请求的数据包时。以下是对代码各个部分的详细解释,帮助您更好地理解这些代码的作用。 代码概述 这段代码主要负责从网络读取数据包,它包含了多个函数来处理网络数据的读取、缓…...
log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件
文章目录 一、DefaultRolloverStrategy1.1、DefaultRolloverStrategy节点1.1.1、filePattern属性1.1.2、DefaultRolloverStrategy删除原理 1.2、Delete节点1.2.1、maxDepth属性 二、知识扩展2.1、DefaultRolloverStrategy与Delete会冲突吗?2.1.1、场景一:…...
macos 支持外接高分辩率显示器开源控制软件
macos 支持外接高分辩率显示器开源控制软件 软件(app应用)名:BetterDisplay 官方地址: https://github.com/waydabber/BetterDisplay...
HTML5实现好看的喜庆圣诞节网站源码
HTML5实现好看的喜庆圣诞节网站源码 前言一、设计来源1.1 主界面1.2 圣诞介绍界面1.3 圣诞象征界面1.4 圣诞活动界面1.5 圣诞热度界面1.6 圣诞纪念界面1.7 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的喜庆圣诞节网站源码,圣…...
鸿蒙 NEXT 开发中,使用公共事件进行进程间通信
大家好,我是 V 哥,在鸿蒙 NEXT 开发中,使用公共事件进行进程间通信(IPC)是一种常见的做法。下面我将提供一个完整的业务代码示例,并解释逻辑关系,以便即使是初学者也能按照步骤进行实操…...
算法-excel表头位置转成对应数字 26进制转10进制
给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ... 示例 1: 输入: columnTitle "A" 输出: 1示例 2: 输入: colu…...
清华发布Hyper-YOLO:超图计算+目标检测!捕捉高阶视觉关联
目录 论文信息 引言 背景 算法概括 超图计算 Hyper-YOLO整体架构 基于超图的跨层次和跨位置表示网络 Coovally AI模型训练与应用平台 实验结论 总结 论文信息 题目:Hyper-YOLO: When Visual Object Detection Meets Hypergraph Computation Hyper-YOLO&a…...
如何使用网络工具进行网络性能评估
网络评估是对IT基础设施的系统评估,以确保它能够很好地满足企业的核心运营需求,确定了基础设施中需要改进的领域,并定义了改进的范围。 网络评估工具分析IT基础设施的各个方面,它通过评估网络设备、网络性能和安全威胁来仔细检查…...
MyBatis执行一条sql语句的流程(源码解析)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 MyBatis执行一条sql语句的流程(源码解析) MyBatis执行sql语句的流程加载配置文件加载配置文件的流程 创建sqlsessionFactory对象解析Mapper创建sqlses…...
使用three.js 实现vr全景图展示,复制即可用
1.实现效果 2.代码 1.npm安装three.js npm install three 2.引入three.js import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls 3.初始化模型 init(val) {this.container document.querySelector(.container)// 初始…...
MATLAB关于集合的运算(部分)
集合运算比较两个集合中的元素,以找出共性或差异 i n t e r s e c t intersect intersect表示两组数据的交集 i s m e m b e r ismember ismember表示查找数据的集合成员 u n i o n union union表示两个数据集的并集 u n i q u e unique unique表示查找数据集的…...
谈谈数据产品开发流程
数据产品开发流程涵盖以下关键步骤:首先是需求调研与规划,通过与业务部门等沟通,明确产品定位、受众及功能,制定项目计划。接着进行数据采集与处理,确定数据源,运用合适工具采集并清洗、转换数据后存储。然…...
Unity3D仿星露谷物语开发12之创建道具列表
1、目标 道具是游戏的核心部分,道具包括你可以拾取的东西,你可以使用的工具和你能种的东西等。 本节就是创建道具的信息类。同时了解ScriptableObject类的使用。 2、创建道具枚举类 修改Assets -> Scripts -> Enums.cs脚本, 新增如…...
Linux(Centos 7.6)常见基础配置
1.网络配置 网络配置详见:VMware安装Linux(Centos 7.6)后网络配置 2.yum源配置 yum源配置详见:Linux(Centos 7.6)yum源配置 3.主机名配置 1.Linux(Centos 7.6)系统安装后,没有配置主机名时,root用户登录后,是如下…...
2024年底关于期货的工作总结
十几年程序猿出身,因几年前的懵懂无畏闯入期货市场,盈了,感觉期货太简单,飘然裸辞,想当财务自由者,全职做交易。当深入学习时,却亏了,原来市场是让人敬畏的,也是反人性的…...
python 插入排序(Insertion Sort)
插入排序(Insertion Sort) 插入排序是一种简单的排序算法。它的基本思想是:将数组分为已排序部分和未排序部分,然后逐个将未排序部分的元素插入到已排序部分的正确位置。插入排序类似于整理扑克牌的过程。 插入排序的步骤&#…...
数据库自增 id 过大导致前端时数据丢失
可以看到,前端响应参数是没有丢失精度的 但是在接受 axios 请求参数时出现了精度丢失 解决方案一:改变 axios 字符编码 axios.defaults.headers[Content-Type] application/json;charsetUTF-8; 未解决 解决方案二:手动使用 json.parse() …...
优化租赁小程序提升服务效率与用户体验的策略与实践
内容概要 在这个快速发展的商业环境中,租赁小程序成为了提升服务效率和用户体验的重要工具。通过对用户需求的深入挖掘,我们发现他们对于功能的便捷性、响应速度和界面的友好性有着极高的期待。因此,针对这些需求,完善租赁小程序…...
nvm node.js 版本管理工具
nvm 介绍 nvm 全称 Node Version Manager 顾名思义它是用来管理 node 版本的工具,方便切换不同版本的Node.js 使用 nvm 的使用非常的简单,跟 npm 的使用方法类似 下载安装 首先先下载 nvm,下载地址 https://github.com/coreybutler/nvm…...
使用Locust对Redis进行负载测试
1.安装环境 安装redis brew install redis 开启redis服务 brew services start redis 停止redis服务 brew services stop redis 安装Python库 pip install locust redis 2.编写脚本 loadTest.py # codingutf-8 import json import random import time import redis …...
计算机网络与通信复习
因特网的核心部分(电路交换与分组交换的不同点,分组交换的优点) 核心部分:路由器、交换机 我们假如数据就是一个货物,比如说一千公斤的大米,电路交换要有专用通道,不管从起点到终点经过多少个…...