哈希表笔记(一 )
设计思路
-
核心功能和 API 设计 (Core Functionality & API Design):
-
基本操作: 必须提供核心的
put(key, value)
(添加或更新键值对)、get(key)
(根据键获取值)、remove(key)
(根据键删除键值对)、containsKey(key)
(检查键是否存在)、size()
(获取元素数量)、isEmpty()
(检查是否为空)、clear()
(清空所有元素)等方法。 -
返回值: 仔细考虑每个操作的返回值。例如,
put
是返回旧值还是void
?remove
是返回被删除的值还是一个布尔值表示成功与否?get
在键不存在时是返回null
、抛出异常,还是返回一个特定的哨兵值或使用 Optional 类型(如果语言支持)? -
迭代: 如何遍历 Map 中的元素?提供迭代器(Iterators)来遍历键、值或键值对(Entries)是常见的做法。API 应清晰易用。
-
批量操作: 是否需要支持如
putAll
等批量操作?
-
-
键(Key)的处理:
-
哈希函数 (Hash Function):
- 质量: 需要一个高质量的哈希函数,能够将键尽可能均匀地分布到哈希桶中,以减少冲突。
- 一致性: 必须保证相等的键(根据
equals
方法判断)必须具有相同的哈希码(hashCode
)。 - 性能: 哈希函数本身的计算速度要快。
-
相等性判断 (Equality):
- 如何判断两个键是否相等?通常依赖于键对象的
equals
方法(或等效的比较函数)。 - 必须同时正确实现
hashCode
和equals
,并遵守它们之间的约定(相等对象必须有相同哈希码)。
- 如何判断两个键是否相等?通常依赖于键对象的
-
不可变性 (Immutability): 强烈建议(或要求)用作键的对象是不可变的。如果一个键在插入 HashMap 后其状态发生改变,导致其
hashCode
或equals
的结果变化,那么可能无法再正确地检索到对应的值。库文档应明确指出这一点。 -
Null 键/值: 是否允许
null
作为键或值?需要明确定义并处理这种情况。Java 的HashMap
允许一个null
键和多个null
值,但Hashtable
不允许。
-
-
冲突解决策略 (Collision Resolution Strategy):
-
当不同的键哈希到同一个索引(桶)时,如何处理?
-
拉链法 (Separate Chaining): 每个桶维护一个数据结构(如链表、红黑树)来存储冲突的键值对。Java 8+ 的
HashMap
在链表长度超过一定阈值时会转换为红黑树,以优化最坏情况下的性能(从 O(n) 降到 O(log n))。 -
开放地址法 (Open Addressing): 当发生冲突时,探测哈希表中的其他位置,直到找到一个空槽。常见的探测方法有线性探测、二次探测、双重哈希等。需要处理删除操作(标记删除而非直接移除,以避免破坏探测链)。
-
选择哪种策略会影响性能特征和实现复杂度。
-
-
性能考量 (Performance Considerations):
-
时间复杂度: 理想情况下,
put
,get
,remove
操作的平均时间复杂度应为 O(1)。但由于冲突和可能的树化(对于拉链法),最坏情况可能是 O(n) 或 O(log n)。 -
空间复杂度: 需要存储键值对本身以及内部数据结构(如哈希表数组、链表节点、树节点)带来的开销。
-
负载因子 (Load Factor): 定义为
元素数量 / 哈希表容量
。当负载因子超过某个阈值时,通常需要进行扩容(Resize)以维持 O(1) 的平均性能。默认负载因子通常在 0.75 左右,这是一个时间和空间成本的权衡。 -
初始容量 (Initial Capacity): 哈希表底层数组的初始大小。如果预知要存储大量元素,设置一个合适的初始容量可以减少扩容次数,提高性能。API 应允许用户指定初始容量和负载因子。
-
扩容机制 (Resizing): 当达到负载因子阈值时,需要创建一个更大的哈希表(通常是原容量的两倍),并将所有现有元素重新哈希(Rehash)到新表中。这是一个相对耗时的操作。
-
-
内存使用 (Memory Usage):
- 内部数据结构的选择(链表 vs. 树 vs. 开放地址)会影响内存占用。
- 负载因子较低意味着空间利用率低,但冲突少;负载因子高则相反。
- 需要考虑每个条目(Entry)的内存开销。
-
并发与线程安全 (Concurrency & Thread Safety):
-
标准 HashMap 实现通常不是线程安全的。如果多个线程同时修改 HashMap,可能会导致数据不一致甚至无限循环(如 JDK 7 及之前版本扩容时可能出现的问题)。
-
如果需要线程安全的版本,需要考虑:
- 完全同步: 使用单一锁保护所有访问(如 Java 的
Hashtable
或Collections.synchronizedMap
),简单但并发性能差。 - 分段锁 (Segmented Locking): 将哈希表分成多个段(Segment),每个段有自己的锁(如 Java 的早期
ConcurrentHashMap
实现)。 - CAS 与无锁技术: 使用现代并发原语(如 Compare-and-Swap)实现更细粒度的并发控制,提供更高的吞吐量(如 Java 8+ 的
ConcurrentHashMap
)。
- 完全同步: 使用单一锁保护所有访问(如 Java 的
-
Java HashMap 实现
JDK7 扩容
// newCapacity为新的容量
void resize(int newCapacity) {// 小数组,临时过度下Entry[] oldTable = table;// 扩容前的容量int oldCapacity = oldTable.length;// MAXIMUM_CAPACITY 为最大容量,2 的 30 次方 = 1<<30if (oldCapacity == MAXIMUM_CAPACITY) {// 容量调整为 Integer 的最大值 0x7fffffff(十六进制)=2 的 31 次方-1threshold = Integer.MAX_VALUE;return;}// 初始化一个新的数组(大容量)Entry[] newTable = new Entry[newCapacity];// 把小数组的元素转移到大数组中transfer(newTable, initHashSeedAsNeeded(newCapacity));// 引用新的大数组table = newTable;// 重新计算阈值threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
JDK8 哈希计算
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
h
是一个 int
类型(在 Java 中是 32 位),右移 16 位并进行异或(XOR)操作的核心原因是为了更好地将原始哈希码的高位信息混合到低位中,以减少哈希冲突,尤其是在哈希表容量较小的时候。
让我们详细解释一下 (h = key.hashCode()) ^ (h >>> 16)
这一步:
h = key.hashCode()
: 首先,获取键key
的原始hashCode()
。这是一个 32 位的int
值。h >>> 16
:>>>
是 Java 中的无符号右移操作符。- 它将
h
的二进制表示向右移动 16 位。 - 由于
int
是 32 位,右移 16 位相当于把原始哈希码的高 16 位移动到了低 16 位的位置。左边空出的位用 0 填充。
^
(XOR):^
是按位异或操作符。- 它将原始的哈希码
h
(包含原始的 32 位信息)与右移 16 位后的值(高 16 位移到了低 16 位,原来的低 16 位丢失,高 16 位补 0)进行异或运算。
为什么这么做?
HashMap 内部通常使用一个数组(称为桶或槽)来存储数据。为了确定一个键值对应该放在数组的哪个位置(哪个桶),HashMap 需要将键的哈希码转换为一个数组索引。这个转换通常是通过取模运算或者(当数组容量是 2 的幂时)位运算 hash & (capacity - 1)
来完成的。
关键在于 hash & (capacity - 1)
这个操作。当 capacity
是 2 的幂时,capacity - 1
的二进制表示是低位全为 1 的一串数字(例如,capacity=16 即 10000
,capacity-1=15 即 01111
)。这意味着,计算索引时,实际上只用到了最终哈希值的低位。
问题来了: 如果一个类的 hashCode()
实现虽然能产生不同的哈希码,但这些差异主要体现在高位,而低位变化不大,那么在使用 hash & (capacity - 1)
计算索引时,不同的键就很容易算得相同的索引,导致大量的哈希冲突,从而降低 HashMap 的性能(查询时间可能从 O(1) 退化到 O(n) 或 O(log n))。
解决方案(即这行代码的作用): 通过 h ^ (h >>> 16)
这个操作,将原始哈希码 h
的高 16 位的信息也**混合(扰动)**到了低 16 位中。这样,即使原始哈希码的差异主要在高位,经过这个混合操作后,这些差异也能体现在最终用于计算索引的低位上。这使得最终的哈希值分布更均匀,减少了冲突的可能性。
总结:
右移 16 位(>>> 16
)是因为 int
是 32 位,这样可以将高 16 位移下来。进行异或(^
)是为了将原始的高位信息和低位信息结合起来,产生一个低位随机性(分布性)更好的哈希值,专门用于后续通过 & (capacity - 1)
计算桶下标,从而有效减少哈希冲突,提高 HashMap 的整体性能。
代码中 (key == null) ? 0 : ...
部分则是处理了 key
为 null
的情况,规定 null
键的哈希值为 0。
为什么不尝试修改hash & (capacity - 1)而是添加低位扰动
它触及了 HashMap 设计中的一个关键权衡:性能与哈希码质量的鲁棒性。
不修改 hash & (capacity - 1)
而选择添加扰动函数(如 h ^ (h >>> 16)
)的主要原因如下:
-
保持最高效的索引计算方式:
-
当哈希表的容量
capacity
设计为 2 的幂时,hash & (capacity - 1)
是计算桶(bucket)索引最快的方式。这利用了位运算 (&
) 的高效性,它通常比取模运算 (%
) 快得多。 -
HashMap 的核心操作(
put
,get
,remove
)都需要计算索引,这个操作的性能至关重要。牺牲这种高效的索引计算方式会显著影响 HashMap 的整体性能。
-
-
无法控制外部
hashCode()
的质量:-
HashMap 作为一个通用库,它无法强制要求所有用作键的对象都实现一个完美的
hashCode()
方法,即一个能将哈希值均匀分布在所有 32 位上的方法。 -
很多时候,用户自定义的类或者甚至 JDK 中的某些类的
hashCode()
实现可能并不理想,产生的哈希码可能在高位区分度好,但在低位区分度差(或者反之,但低位差更影响&
运算)。 -
如果 HashMap 不做任何处理,直接使用
key.hashCode() & (capacity - 1)
,那么一旦遇到低位分布不佳的哈希码,就会导致大量的冲突,性能急剧下降。
-
-
扰动函数是对"坏"
hashCode()
的一种"防御":-
添加
h ^ (h >>> 16)
这样的扰动步骤,其目的是将原始哈希码的高位信息也混合到低位中。 -
这样做的好处是,即使原始
hashCode()
的低位区分度不高,但只要高位具有一定的区分度,通过扰动函数,这种区分度也能"传递"到最终用于索引计算的低位上。 -
这使得 HashMap 对各种不同质量的
hashCode()
实现更加鲁棒(robust),降低了因为糟糕的hashCode()
实现而导致严重哈希冲突的风险。它是一种补偿机制。
-
-
职责分离:
-
可以认为
key.hashCode()
的职责是为对象生成一个(尽可能唯一的)整数表示。 -
HashMap 内部
hash()
函数的职责是获取这个整数表示,并将其转换为一个适合在内部数组中定位的、分布尽可能均匀的值。 -
而
hash & (capacity - 1)
的职责是利用这个优化后的哈希值,以最高效的方式计算出最终的数组下标。 -
添加扰动函数是在不改变最高效索引计算的前提下,优化了传递给索引计算的值。
-
总结:
选择添加扰动函数而不是修改 hash & (capacity - 1)
,是在性能和鲁棒性之间做出的明智权衡。
-
保留
hash & (capacity - 1)
是为了极致的索引计算性能。 -
添加扰动函数是为了增强对各种质量
hashCode()
实现的适应性,通过混合高位和低位信息,减少仅仅依赖低位可能带来的冲突风险,从而提高整体的性能稳定性。
这体现了库设计者在面对无法控制的外部因素(hashCode()
实现)时,通过内部优化来尽可能保证库自身性能和可靠性的策略。
取模运算 VS 取余运算 VS 与运算
取模运算(Modulo Operation)和取余运算(Remainder Operation)从严格意义上来讲,是两种不同的运算方式,它们在计算机中的实现也不同。
在 Java 中,通常使用 % 运算符来表示取余,用 Math.floorMod()
来表示取模。
- 当操作数都是正数的话,取模运算和取余运算的结果是一样的。
- 只有当操作数出现负数的情况,结果才会有所不同。
- 取模运算的商向负无穷靠近;取余运算的商向 0 靠近。这是导致它们两个在处理有负数情况下,结果不同的根本原因。
- 当数组的长度是 2 的 n 次方,或者 n 次幂,或者 n 的整数倍时,取模运算/取余运算可以用位运算来代替,效率更高,毕竟计算机本身只认二进制嘛。
hash & (capacity - 1)和hash % capacity 有区别吗
核心区别:
-
操作类型:
-
%
: 是**取模(Modulo)**运算,计算hash
除以capacity
后的余数。 -
&
: 是**按位与(Bitwise AND)**运算,对hash
和capacity - 1
的二进制表示进行逐位与操作。
-
-
对
capacity
的要求:-
%
: 适用于任何正整数capacity
。无论capacity
是多少,hash % capacity
都能正确地将hash
映射到[0, capacity - 1]
的范围内。 -
&
: 只有当capacity
是 2 的幂(Power of 2)时,hash & (capacity - 1)
的结果才等价于hash % capacity
,并且能有效地将hash
均匀映射到[0, capacity - 1]
的范围。如果capacity
不是 2 的幂,hash & (capacity - 1)
的结果虽然也在[0, capacity - 1]
范围内(但不一定覆盖整个范围),但与取模结果不同,并且会导致哈希分布非常不均匀(某些桶永远不会被用到)。
-
-
性能:
-
%
: 取模运算(尤其是涉及除法)通常比位运算慢。 -
&
: 按位与运算是非常快的,是处理器可以直接执行的基本指令。
-
为什么 capacity
是 2 的幂时 &
操作有效?
当 capacity
是 2 的幂时(例如 16),它的二进制表示是 1
后面跟着若干个 0
(例如 16 是 10000
)。 那么 capacity - 1
的二进制表示就是若干个 1
(例如 15 是 01111
)。
执行 hash & (capacity - 1)
操作时,这个 capacity - 1
(形如 0...011...1
)就像一个掩码(mask),它会保留 hash
值中对应 1
位置的那些低位比特,并将对应 0
位置的高位比特全部清零。保留下来的低位比特数正好是 log2(capacity)
。这在数学上恰好等价于计算 hash
除以 capacity
(2的幂) 的余数。
举例说明:
假设 hash = 123
场景 1: capacity = 16
(是 2 的幂, 2^4)
-
capacity - 1 = 15
-
二进制表示:
-
hash = 123
->01111011
-
capacity - 1 = 15
->00001111
(掩码,保留低 4 位)
-
-
取模运算:
123 % 16 = 11
-
按位与运算:
-
01111011 & 00001111 = 00001011
(二进制) -
00001011
(二进制) = 11 (十进制)
-
-
结果: 两者结果相同(都是 11)。使用
&
更快。
场景 2: capacity = 10
(不是 2 的幂)
-
capacity - 1 = 9
-
二进制表示:
-
hash = 123
->01111011
-
capacity - 1 = 9
->00001001
-
-
取模运算:
123 % 10 = 3
(这是我们期望的、能利用所有 10 个桶的索引)
-
按位与运算:
-
01111011 & 00001001 = 00001001
(二进制) -
00001001
(二进制) = 9 (十进制)
-
-
结果: 两者结果不同(3 vs 9)。
-
更严重的问题: 观察
capacity - 1 = 9
的二进制1001
。它只有第 0 位和第 3 位是 1。这意味着,无论hash
值是多少,hash & 9
的结果中,第 1 位和第 2 位永远是 0。-
可能的结果只有:
0000
(0),0001
(1),1000
(8),1001
(9)。 -
这意味着,如果数组大小是 10,使用
hash & 9
来计算索引,那么索引 2, 3, 4, 5, 6, 7 的桶永远不会被使用!这会导致哈希冲突急剧增加,性能严重下降。
-
总结:
特性 | hash % capacity | hash & (capacity - 1) |
---|---|---|
操作 | 取模 (求余数) | 按位与 |
capacity | 任何正整数 | 必须是 2 的幂 |
性能 | 相对较慢 | 非常快 |
结果 | 范围 [0, capacity-1] ,分布均匀 | 范围 [0, capacity-1] ,仅当 capacity 是 2 的幂时分布均匀且等价于取模 |
HashMap 应用 | 理论可行,但因性能较差通常不直接用 | 实际采用,配合内部将 capacity 调整为 2 的幂的策略 |
因此,像 Java 的 HashMap
这样的实现选择使用 hash & (capacity - 1)
是为了获得极致的性能,但其前提是内部强制要求哈希表的容量 (capacity
) 始终是 2 的幂。这也是为什么你在看 HashMap
源码时会发现,当你指定一个初始容量时,它内部会找到大于等于该值的最小的 2 的幂作为实际容量;并且在扩容时,总是将容量翻倍(乘以 2),以保持其为 2 的幂。之前讨论的 hash()
函数扰动(如 h ^ (h >>> 16)
)也是为了配合这种基于低位掩码的索引计算方式,让高位的差异也能影响最终的低位索引。
相关文章:
哈希表笔记(一 )
设计思路 核心功能和 API 设计 (Core Functionality & API Design): 基本操作: 必须提供核心的 put(key, value)(添加或更新键值对)、get(key)(根据键获取值)、remove(key)(根据键删除键值对)、contain…...
c网络库libevent的http常用函数的使用(附带源码)
Libevent HTTP 核心函数详解与实战 核心概念HTTP 服务器端常用函数1. 初始化与绑定2. 设置请求处理回调3. 在回调函数中处理请求4. 发送响应5. 启动与停止6. 清理资源 HTTP 客户端常用函数1. 初始化2. 创建连接3. 创建并发送请求4. 在回调函数中处理响应5. 启动事件循环与清理 …...
java练习3
随机生成20个数字(随机种子) 分别使用冒泡排序、二叉树排序、插入排序进行排序 并输出最终结果以及三种排序使用的时间 package a01_第一次练习.a03_排序;import java.time.Duration; import java.time.LocalDateTime; import java.util.TreeSet;publi…...
当 AI 成为 “数字新物种”:人类职业的重构与进化
一、AI 的 “替代清单”:从流水线到办公室的全面侵袭 在深圳某智能工厂,机械臂正以 0.01 毫米的精度完成手机组装,100 台机器人 24 小时运转,替代了 3000 名工人。这种场景正在全球制造业蔓延 —— 麦肯锡预测,到 203…...
HarmonyOS ArkUI交互事件与手势处理全解析:从基础到高级实践
文章目录 一、交互事件1.1 通用事件1.1.1 事件分发1.1.1.1 触摸测试1. 触摸测试基本流程2. 触摸测试控制3. 自定义事件拦截4. 禁用控制5. 触摸热区设置6. 安全组件 1.1.1.2 事件响应链收集 1.1.2 触屏事件1.1.3 键鼠事件1.1.3.1 鼠标事件1.1.3.2 按键事件 1.1.4 焦点事件1.1.5 …...
【计算机网络】面试常考——GET 和 POST 的区别
GET 和 POST 的区别 GET 和 POST 是 HTTP 协议中最常用的两种请求方法,它们的主要区别体现在 用途、数据传输方式、安全性、缓存机制 等方面。以下是详细对比: 1. 用途 GET POST 主要用于 获取数据(如查询、搜索)。 主要用于 提…...
AI编程工具“幻觉”风险与飞算JavaAl的破局之道
近年来,AI编程辅助工具迅速崛起,极大地提升了开发者的工作效率。然而,这些工具普遍存在一个被称为“幻觉”(hallucination)的风险——AI可能会生成看似合理但实际错误、不安全或低效的代码。这种现象在复杂业务逻辑和特定领域开发中尤为明显&…...
【Python零基础入门系列】第1篇:Python 是什么?怎么装环境?推荐哪些 IDE?
各位网友们,欢迎来到我的 Python 学习专栏! 前两天看到新闻英伟达为 CUDA 添加原生 Python 支持,意味着开发者可直接用 Python 操作 GPU,加速 AI 和高性能计算,降低门槛,让 Python 的应用范围更广、能力更强。 一直想写一系列文章教知友们从零开始学会 Python 编程,目…...
VPN访问SAP组服务器报登陆负载均衡错误88:无法连接到消息服务器(RC=9)
用户反馈用SAPGUI接入SAP时报错:登陆负载均衡错误88:无法连接到消息服务器(RC9) 经了解是通过VPN访问,但VPN没有放行ICMP访问,导致不能PING通,不能确认是网络问题还是什么问题。 解决方案: 1、VPN由原&am…...
Linux查看程序端口占用情况
大家好,欢迎来到程序视点!我是你们的老朋友.小二! 核心问题: Tomcat 8080端口启动失败,提示端口被占用,但常规检查未发现Tomcat进程占用该端口。 关键排查步骤: 初步检查 使用 ps -aux | gre…...
[C]基础14.字符函数和字符串函数
博客主页:向不悔本篇专栏:[C]您的支持,是我的创作动力。 文章目录 0、总结1、字符分类、转换函数2、strlen的使用和模拟实现2.1 strlen的使用2.2 strlen的模拟实现 3、strcpy的使用和模拟实现3.1 strcpy的使用3.2 strcpy的模拟实现 4、strcat…...
三种机器学习类型
本文讲介绍三种机器学习类型:①监督学习,②无监督学习,③强化学习。我们主要了解监督学习和无监督学习即可。 下图介绍这三种机器学习类型的区别: 1 用来预测未来的监督学习 从有标签的训练数据中学习一个模型,用来…...
UE5 Set actor Location和 Set World Location 和 Set Relative Location 的区别
在 Unreal Engine 的蓝图里,SetRelativeLocation、SetWorldLocation 和 SetActorLocation 三个节点虽然都能改变物体位置,但作用对象和坐标空间(Coordinate Space)不同: 1. SetActorLocation 作用对象:整个…...
Glide 如何加载远程 Base64 图片
最近有个需求,后端给出的图片地址并不是正常的 URL,而且需要一个接口去请求,但是返回的是 base64 数据流。这里不关心为啥要这么多,原因有很多,可能是系统的问题,也可能是能力问题。当然作为我们 Android 程…...
JVM对象存储格式
引言 在Java虚拟机(JVM)中,对象的内存布局是一个重要的底层概念,它直接影响对象在内存中的存储方式和占用空间。了解对象存储格式不仅有助于优化程序性能,还能帮助我们更好地理解JVM的工作原理。本文将详细探讨对象存…...
3D Gaussian Splatting部分原理介绍和CUDA代码解读
本系列旨在帮助无CUDA代码经验的读者、以及3DGS的初学者理解代码逻辑。 3D GS论文原文链接:https://arxiv.org/abs/2308.04079 论文笔记链接:【论文笔记】3D Gaussian Splatting for Real-Time Radiance Field Rendering 【论文笔记】A Survey on 3D Ga…...
日本IT行业|salesforce开发语言占据的地位
在日本的IT行业中,Salesforce 开发语言处于一个较为专业但稳步增长的细分领域,并不是主流开发语言(如 Java、Python、PHP),但其在某些行业和场景中地位越来越重要。 本篇以下是详细分析: Salesforce开发语言…...
1.1 点云数据获取方式——引言
图1-1-1点云建筑场景图 点云数据是指能够描述外部场景、对象表面的三维空间位置,并具有相关属性的点集,其每个离散点通常包括三维空间位置(x,y,z)以及强度、颜色等属性信息。大量分布的离散点集能够清晰而直接地描绘场景、对象的3…...
接入层架构演变
1、单体架构 请求过程 浏览器的请求通过 DNS Server 解析到指定的 IP 地址,浏览器通过 IP 地址访问 Web Server 缺点 当到达 Web Server 的性能瓶颈时(瓶颈受到CPU,内存,io,带宽影响),无法进…...
python:sklearn 主成分分析(PCA)
参考书:《统计学习方法》第2版 第16章 主成分分析(PCA)示例 编写 test_pca_1.py 如下 # -*- coding: utf-8 -*- """ 主成分分析(PCA) """ import matplotlib.pyplot as plt from skl…...
力扣-数据结构-二叉树
94. 二叉树的中序遍历 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示例 2: 输入:root [] 输出:[]示例 3: 输入&#x…...
嵌入式音视频实时通话EasyRTC打造设备安装与调试的高效远程解决方案
一、背景 在数字化浪潮席卷全球的今天,实时音视频通信技术已经成为众多领域不可或缺的重要组成部分。从智能家居到智能安防,从在线教育到远程医疗,人们对于高效、便捷、稳定且低延迟的音视频通信解决方案的需求日益迫切。而EasyRTC作为一款卓…...
AI 的未来是开源?DeepSeek 正在书写新篇章!
AI 的未来是开源?DeepSeek 正在书写新篇章! 随着人工智能(AI)技术的迅猛发展,越来越多的企业和研究机构开始关注 AI 的开放性和透明度。开源不仅能够促进技术创新,还能加速知识的传播和应用。在这个背景下…...
抢先体验全新极小大模型Qwen3:0.6B
全民都在期待DeepSeek-R2的发布,但是一不小心被阿里截胡了,2025 年 4 月 29 日,阿里巴巴发布并开源了通义千问 Qwen3 系列大模型。据 大模型镜像网站 上关于Qwen3的介绍: Qwen3 是 Qwen 系列中最新一代的大型语言模型,提供一整套密集模型和混合专家 (MoE) 模型。Qwen3 基…...
部署一个自己的Spring Ai 服务(deepseek/通义千问)
Spring Boot 无缝接入 DeepSeek 和通义千问请求日志记录及其ip黑白名单 SpringBoot版本 3.2.0 JDK 版本为17 redis 3.2.0 mybatis 3.0.3 依赖引入 关键依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-sp…...
第一讲 | 算法复杂度
算法复杂度 一、数据结构前言1、数据结构(DS)2、算法(Algorithm) 二、算法效率1、复杂度的概念 三、时间复杂度(1)、案例(2)、大O的渐进表示法(3)、时间复杂度…...
【运维】还原 Docker 启动命令的利器:runlike 与 docker-autocompose
🔍 还原 Docker 启动命令的利器:runlike 与 docker-autocompose 实用教程 在日常使用 Docker 时,我们常常通过 docker run 启动容器,但有时候过了一段时间就忘记了当初使用的具体参数(端口、挂载、环境变量等…...
IP属地是实时位置还是自己设置
刷微博、抖音时,评论区总能看到“IP属地”?这个突然冒出来的小标签,让不少网友摸不着头脑:IP属地是实时位置,还是可以自己设置?别急,今天咱们就来聊聊这个话题! 1、什么是IP属地…...
Android WIFI体系
先说说WifiLock、MulticastLock 、IWificond WifiLock 允许应用强制保持 WiFi 活跃,即便设备处于休眠状态。如WIFI_MODE_FULL_HIGH_PERF:保持高性能 WiFi 活跃状态,适用于高带宽需求,如视频通话、流媒体。经测试有的场景能减少10…...
什么是静态住宅ip,跨境电商为什么要用静态住宅ip
在数字时代,IP地址不仅是设备联网的“ID”,更是跨境电商运营中的关键工具。尤其对于需要长期稳定、安全操作的场景,静态住宅IP逐渐成为行业首选。 一、什么是静态住宅IP? 静态住宅IP(Static Residential IP࿰…...
常见位运算总结
目录 常见位运算总结 191:位1的个数 338:比特位计数 461:汉明距离 136:只出现一次的数字 260:只出现一次的数字III 常见位运算总结 191:位1的个数 链接:191. 位1的个数 - 力扣(LeetCode) class Sol…...
[密码学实战]SDF之对称运算类函数(四)
[密码学实战]SDF之对称运算类函数(四) 一、标准解读:GM/T 0018-2023核心要求 1.1 SDF接口定位 安全边界:硬件密码设备与应用系统间的标准交互层 功能范畴: #mermaid-svg-1jptduZFNFiRZ2lS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16…...
【C++编程入门】:基本语法
上一篇提到了C关键字和缺省参数以及命名空间域,这篇继续分享C入门语法,把基本语法掌握扎实后面学习更才能更轻松一些。 目录 引用 引用的特性 常引用 内联函数 auto关键字 引用 引用不是新定义一个变量,而是给已存在变量取了一个别名&am…...
区块链最佳框架:Truffle vs Hardhat vs Brownie
区块链技术的快速发展使得智能合约开发成为主流,而选择合适的开发框架是提升效率的关键。目前,Truffle、Hardhat和Brownie是三大主流框架,它们各有特点,适用于不同的开发场景和开发者偏好。本文将从功能、生态系统、适用人群等角度…...
Apache Flink的架构设计与运行流程说明
在大数据领域,实时计算的重要性随着业务需求的爆发式增长愈发凸显。从电商的实时销量监控到金融的高频交易风控,从物联网设备的实时告警到社交平台的热点追踪,企业对“秒级甚至毫秒级”数据处理能力的需求已成为刚需。在众多实时计算框架中&a…...
AI+零售:智能推荐、无人店与供应链管理的未来
AI零售:智能推荐、无人店与供应链管理的未来 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 AI零售:智能推荐、无人店与供应链管理的未来摘要引言一、智能推荐系统:从流量收割到用…...
华为云IoT平台与MicroPython实战:从MQTT协议到物联网设备开发
目录 前言 1. 华为云 1.1. 创建实例 1.2. 创建产品 1.3. 编辑服务模型 1.4. 注册设备 1.4.1. 复制设备连接参数 1.5. 连接参考代码 2. micropython版-物联网 2.1. 环境搭建 2.2. 实现步骤 2.3. 示例代码 结语 前言 物联网(IoT)技术的快速发…...
【Linux】Linux内核模块开发
Linux内核模块开发 零、关于 1、概述 最近在学习Linux相关的东西,学习了U-Boot的编译,Linux的编译,能够在开发板上运行自己编译的U-Boot和Linux了,那么接下来就是在自己编译的Linux上做应用级或者系统级的开发了。本文以字符设…...
linux 下查看指定进程的内存CPU占用情况(用于程序崩溃类的排查)
在程序开发过程中,如果程序较为庞大,逻辑较为复杂时,容易出现运行时崩溃的问题。导致的原因有很多,我这里只对较为通用的内容占用情况作记录,如程序中对文件描述符打开未关闭(导致fd积攒过多超过了系统的标…...
ASP.NET MVC 入门指南五
26. 响应式设计与移动开发 26.1 响应式视图设计 为了使 MVC 应用程序在不同设备上都能提供良好的用户体验,需要采用响应式设计。可以使用 CSS 框架如 Bootstrap 来实现响应式布局。 引入 Bootstrap:在项目中引入 Bootstrap 的 CSS 和 JavaScript 文件。…...
字节跳动社招面经 —— BSP驱动工程师(4)
接前一篇文章:字节跳动社招面经 —— BSP驱动工程师(3) 本文内容参考: 嵌入式硬件平台修改启动地址-CSDN博客 特此致谢! 上一回开始针对于“嵌入式充电站”发的一篇文章字节跳动社招面经——BSP驱动工程师中的面试题…...
Spring MVC中自定义日期类型格式转换器
在Spring MVC中,自定义日期类型格式转换器可以通过实现Converter接口或使用DateTimeFormat注解。以下是两种方法的详细说明: 方法一:全局自定义转换器(推荐) 1. 创建日期转换器类 实现 org.springframework.core.con…...
【3D 地图】无人机测绘制作 3D 地图流程 ( 无人机采集数据 | 地图原始数据处理原理 | 数据处理软件 | 无人机测绘完整解决方案 )
文章目录 一、无人机采集数据1、多角度影像数据2、定位与姿态数据 二、无人机采集数据处理原理1、空三解算2、密集点云生成与三维重建3、地形与正射影像生成4、三维模型优化与瓦片化 三、无人机影像处理软件介绍 一、无人机采集数据 无人机原始数据采集 : 多角度影像数据 : 多…...
arduino Nano介绍
【仅供学习,具体参数参考官网或销售商】 Arduino Nano 是一款基于 ATmega328P 微控制器(或 ATmega168 旧版)的紧凑型开发板,专为嵌入式项目和原型设计而设计。 以下是Arduino Nano V3.0 328P详细介绍: 主要特性 微…...
解决 Flutter 在 iOS 真机上构建失败的问题
在开发 Flutter 应用时,有时会在尝试将应用部署到 iOS 真机时遇到构建失败的问题。错误信息通常类似于以下内容: Could not build the precompiled application for the device. Uncategorized (Xcode): Timed out waiting for all destinations matchi…...
【办公类-89-03】20250429AI写的研讨记录,清除格式,统一格式,名字替换。部分加粗,添加页眉
背景需求: 检查自即,需要AI一下院内的五次科研培训记录。 本次用了豆包 豆包写的不错,也是“水字数”的高手 把每次培训内容贴到WORD里 把AI资料贴到WORD里,发现问题: 1、字体、段落什么都是不统一的,需要统一改成宋体小四,1.5倍行距 2、十个研讨人也要改成真人。就找…...
react-native 安卓APK打包流程
一、使用keytool命令生成一个签名密钥 $ keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 在 Windows 上keytool命令放在 JDK 的 bin 目录中(比如C:\Program Files\…...
Android Studio中OpenCV应用详解:图像处理、颜色对比与OCR识别
文章目录 一、OpenCV在Android中的集成与配置1.1 OpenCV简介1.2 在Android Studio中集成OpenCV1.2.1 通过Gradle依赖集成1.2.2 通过模块方式集成1.2.3 初始化OpenCV 1.3 OpenCV基础类介绍 二、指定区域图像抓取与对比2.1 图像抓取基础2.2 指定区域图像抓取实现2.2.1 从Bitmap中…...
企业办公协同平台安全一体化生态入住技术架构与接口标准分析报告
全球组织数字化与智能化背景下 企业办公协同平台安全一体化生态入住技术架构与接口标准分析报告 一、背景与市场需求 市场规模与增量 根据Statista数据,全球协同办公平台市场规模预计从2023年的$480亿增长至2027年的$900亿,年复合增长率(CAG…...
从零搭建体育比分网站:技术选型与API调用实战(附完整源码)
一、前言:为什么选择体育比分项目? 体育数据网站是练手全栈开发的绝佳项目,涉及: ✅ 前端(实时数据渲染、可视化图表) ✅ 后端(API对接、数据缓存、高并发优化) ✅ 数据库ÿ…...