- 博客(41)
- 资源 (2)
- 问答 (2)
- 收藏
- 关注
原创 @Configuration注解的配置类
在Spring Boot中,使用@Configuration注解的配置类不需要强制放到特定的包路径下,但需要确保配置类能被Spring的组件扫描机制发现。Spring Boot的主启动类(带@SpringBootApplication的类)默认会扫描当前包及其所有子包下的组件(包括@Configuration类)。主模块的组件扫描范围包含该模块的包路径(通过 @ComponentScan 指定)。com.example.demo.config(子包)若配置类不在这些路径下,需手动指定扫描范围。
2025-03-18 15:37:48
332
原创 浏览器中输入 URL 到显示主页的完整过程
URL 解析 → DNS 查询 → TCP 握手 → TLS 握手(HTTPS)→ 发送 HTTP 请求 → 服务器处理 → 接收响应 → 解析 HTML/CSS → 构建渲染树 → 布局 → 绘制 → 加载子资源 → 页面展示。输入处理:浏览器解析 URL 格式(协议、域名、路径、参数等),若未指定协议(如直接输入 example.com),默认补全为 http:// 或 https://。资源压缩:Gzip、Brotli 压缩文本;状态码:200(成功)、301(重定向)、404(未找到)等。
2025-03-14 19:52:38
470
原创 String类型为什么不可变
在大多数编程语言(如 Java、Python、C# 等)中,String 类型被设计为不可变(Immutable),这意味着一旦一个字符串对象被创建,它的值就不能被修改。作为不可变对象,String 的行为可预测,例如作为参数传递时无需担心副作用(Side Effect)。防止意外修改:字符串常用于 URL、文件路径、密码等场景,不可变性保证这些敏感数据不会被篡改。String 不可变的核心原因:安全性、性能优化(常量池、哈希缓存)、设计一致性。何时使用可变字符串:频繁修改字符串内容的场景(如循环拼接)。
2025-03-14 19:24:23
426
原创 TCP 采用三次握手建立连接的原因
问题:若此时客户端认为这是无效连接(例如旧的连接已关闭),会直接忽略服务端的 SYN-ACK。消除历史连接:如果客户端收到的是旧 SYN-ACK(来自历史连接),会回复 RST 终止连接,避免服务端误建连接。服务端回复 SYN-ACK,携带自己的初始序列号(seq=y)和对客户端 SYN 的确认号(ack=x+1)。客户端确认:通过第二次握手(服务端回复 SYN-ACK),客户端确认服务端的发送和接收能力正常。服务端确认:通过第三次握手(客户端回复 ACK),服务端确认客户端的接收能力正常。
2025-03-14 18:58:44
583
原创 Redis 常用数据类型
描述:Redis 5.0+ 引入的日志型数据结构,支持消息持久化和消费者组。描述:最基本的数据类型,可存储文本、数字或二进制数据(最大 512MB)。SETBIT key offset value:设置位的值(0/1)描述:按插入顺序排序的字符串列表,支持双向操作(类似队列或栈)。描述:元素唯一且按分数(score)排序的集合,可实现范围查询。描述:用于估算集合中唯一元素的数量(误差率约 0.81%)。LRANGE key start end:获取范围内的元素。
2025-03-14 16:16:08
449
原创 java匿名子类
在 Java 中,匿名子类(Anonymous Subclass) 是一种不显式定义类名、直接通过继承父类或实现接口的方式创建新类的技术。它通常用于快速实现某个接口或覆盖父类的方法,尤其是在需要临时定义一次性使用的类时。匿名子类的类名是编译器生成的(如 Outer$1),序列化和反序列化时可能因类名变化导致异常。避免滥用:在需要性能优化或长期维护的代码中,优先使用 Lambda、静态内部类或工厂方法。注意内存泄漏:在非静态上下文中,匿名子类会隐式持有外部类的引用。方法区(Metaspace)内存占用上升。
2025-03-14 11:34:46
351
原创 回溯法--力扣第17题“电话号码的字母组合”(java)
回溯法通过递归遍历每个数字对应的字母,生成所有可能的组合。核心思想是构建搜索树,每次选择一个字母后进入下一层递归,回溯时撤销选择以尝试其他分支。构建数字到字母的映射表:使用数组或哈希表存储每个数字对应的字母。终止条件:当前路径长度等于输入数字字符串长度时,将结果加入列表。遍历当前数字对应的所有字母,依次选择、递归、撤销选择。力扣第17题“电话号码的字母组合”
2025-03-14 04:26:00
386
原创 双路快排--力扣215.数组中的第K个最大元素(java)
快速选择算法:基于快速排序的分区思想,每次选择一个基准元素将数组分为两部分,左边的元素小于等于基准,右边的元素大于基准。//缩小搜索范围:根据基准元素的位置与目标位置(n - k)的比较,决定继续处理左半部分还是右半部分。随机化基准:通过随机选择基准元素,避免最坏时间复杂度,提高算法效率。
2025-03-13 23:44:24
230
原创 力扣215.数组中的第K个最大元素--堆排序法(java)
为了找到数组中第K个最大的元素,我们可以使用堆排序的方法。堆排序的核心是构建一个最大堆,并通过多次交换堆顶元素来找到前K个最大的元素。交换并调整堆:执行K次交换操作,每次将堆顶元素(当前最大值)与当前堆的末尾元素交换,然后调整剩下的元素以维持最大堆的性质。构建最大堆:将输入数组转换为最大堆,使得每个父节点的值大于其子节点的值。获取结果:经过K次交换后,第K个最大的元素会位于数组的倒数第K个位置。
2025-03-13 19:10:05
169
原创 JVM类加载机制和双亲委派
JVM类加载机制是Java程序运行的核心基础,负责将.class文件加载到内存,并转化为可执行的类对象。加载(Loading)通过类加载器查找类的二进制数据(如.class文件或网络资源),生成对应的Class对象。连接(Linking)验证(Verification):检查字节码是否符合JVM规范,防止恶意代码注入。准备(Preparation):为静态变量分配内存并设置初始值(如int类型初始化为0)。解析(Resolution):将符号引用转换为直接引用(例如将类名映射到内存地址)。
2025-03-13 01:20:53
465
原创 Java线程安全
线程安全指多线程环境下,程序能正确且一致地处理共享资源的状态,不会因线程调度顺序导致数据不一致或逻辑错误。例如多个线程同时修改共享变量时,需通过同步机制确保操作原子性。:实现线程安全的计数器。
2025-03-13 00:20:48
641
原创 Lock接口与synchronized锁机制
Lock接口是Java并发包(JUC)中定义的锁机制,提供比synchronized更灵活的控制方式。,通过构造参数指定。公平锁按等待顺序分配锁,非公平锁允许插队以提高吞吐量。synchronized是JVM层面的内置锁,通过。
2025-03-13 00:16:32
352
原创 Java volatile 关键字详解
(Memory Barrier)禁止编译器和处理器对指令进行重排序,保证代码执行顺序符合预期。volatile 修饰的变量在修改后,会立即同步到主内存,其他线程读取时直接从主内存获取最新值,确保多线程环境下的可见性。变量仅被单线程修改,其他线程只读(如配置参数)。后,线程B能立即感知到变化。volatile 通过插入。
2025-03-12 23:00:38
1113
原创 Java CAS(Compare-And-Swap)概念及原理
当且仅当内存位置V的值等于预期值A时,才会将V的值更新为B,否则不执行操作。整个过程是原子的,无需加锁即可保证线程安全。CAS(Compare-And-Swap)是一种无锁编程的核心技术,用于实现多线程环境下的原子操作。这一过程通过硬件指令(如CAS指令)保证原子性,无需锁机制。此处通过循环CAS实现安全的计数器自增,避免了锁的使用。方法即为CAS操作,底层依赖。类调用CPU指令(如x86的。
2025-03-12 21:51:35
355
原创 java中的队列Queue
Queue是Java集合框架中定义的队列接口,遵循**先进先出(FIFO)**原则。添加元素: 队列未满时添加元素,否则抛出异常: 安全添加元素,队列满时返回false移除元素E remove(): 移除并返回队首元素,空队列时抛出异常E poll(): 安全移除元素,空队列时返回null检查元素: 查看队首元素,空队列时抛出异常E peek(): 安全查看元素,空队列时返回null。
2025-03-12 21:36:24
294
原创 @RestControllerAdvice注解
RestControllerAdvice 是 Spring Framework(3.2+)和 Spring Boot 中用于全局处理控制器层异常和统一响应格式的注解。它结合了 @ControllerAdvice 和 @ResponseBody 的功能,能够拦截控制器方法抛出的异常,并以 JSON/XML 格式返回处理结果。捕获所有控制器(@RestController)抛出的异常,避免重复编写异常处理代码。统一处理参数校验(如 @Valid)失败时的错误响应。具体异常类型的处理器优先于通用异常处理器。
2025-03-12 21:26:14
438
原创 Spring中常用依赖注入注解的详细说明
在Spring框架中,依赖注入(DI)是实现松耦合的关键机制,主要通过注解简化配置。来源:JSR-330标准(javax.inject),需引入依赖(如javax.inject:javax.inject:1)。来源:Spring框架(org.springframework.beans.factory.annotation)。作用:当存在多个相同类型Bean时,按名称(byName)消除歧义。作用:默认按名称(byName)注入,支持字段和setter方法。来源:Spring框架。来源:Spring框架。
2025-03-06 19:19:32
193
原创 String 类中常用的方法(java)
不可变性:所有字符串修改操作都会生成新字符串,原字符串不变。去除字符串首尾的空白字符(空格、制表符、换行等)。返回子字符串第一次出现的索引,未找到返回 -1。检查字符串是否以指定前缀/后缀开头或结尾。按字典顺序比较两个字符串(区分大小写)。使用正则表达式替换所有匹配的子字符串。比较字符串内容是否相等(区分大小写)。将指定字符串连接到当前字符串末尾。检查字符串是否为空(长度为 0)。判断字符串是否匹配正则表达式。判断是否包含指定的子字符串。截取指定索引范围的子字符串。使用格式字符串生成新字符串。
2025-03-05 15:48:30
370
原创 command not found pip解决办法
mac默认安装python2,安装python3和vs code后用pip安装,出现command not found pip,用pip install改为pip3 install就好了。
2025-03-04 14:22:14
189
原创 基于 OpenAI ChatGPT 3.5 的 LangGraph 对话机器人示例
state[“history”].append({“user”: user_input}) # 更新历史。state = {“history”: [{“user”: “你好”}]} # 初始对话历史。作用:创建一个初始的 ChatState 对象,包含用户的第一条消息 “你好”。【初始化】 state.history = [{“user”: “你好”}]ai_reply 检测到 “退出”,返回结束回复 “对话结束,再见!逻辑:检查 AI 的回复中是否包含 “退出”(本例未触发,继续循环)。
2025-03-02 02:17:27
839
1
原创 回溯算法--数组/和/差值最小
10个数字分成两组,每组5个,让第一个数组的和与第二个数组的和的差最小值。时间复杂度:O(C(10,5)) = 252次组合计算,属于可行范围。当选中5个元素时,计算当前组合和与总和的差值。空间复杂度:O(n) 递归深度最大为10层。双分支分别处理选择/不选择当前元素的情况。读取一行输入并分割为字符串数组。计算数组总和用于后续差值计算。递归遍历所有可能的5元素组合。验证输入必须包含10个整数。通过索引递增避免重复计算。将字符串转换为整型数组。初始化最小差值为极大值。
2025-02-25 02:33:29
327
原创 java中ArrayList用法
它的常用方法包括 add()、get()、set()、remove()、size() 等。如果你知道列表的大小,也可以传入 new String[list.size()],但 new String[0] 更常用且简洁。(list.toArray(new String[0]) 是将 ArrayList 转换为 String[] 数组的标准写法。// 将第二个元素从 “Banana” 修改为 “Mango”
2025-02-23 22:57:22
655
原创 算法题:喊7的次数重排
一群人围成一圈玩报数游戏,从1开始报数,遇到7的倍数或数字包含7时,不报数而是喊“过”。请统计每个人喊“过”的次数,并按照输入顺序输出每个人的喊“过”次数。4个人围成一圈,报数序列为:1, 2, 3, 4, 5, 6, 过, 8, 9, 10, 11, 12, 13, 过, …从1开始报数,遇到7的倍数或数字包含7时,当前报数的人喊“过”。模拟报数过程,遇到7的倍数或包含7的数字时,当前人喊“过”。空间复杂度:O(n),用于存储每个人喊“过”的次数。喊“过”的次数分别为:0, 1, 1, 1。
2025-02-22 16:56:38
450
原创 单调栈--分奖金
第一个员工(2)向后找到第一个比自己大的数字是 10,距离为 1,差值为 8,奖金为 1 × 8 = 8。单调栈适用于类似的查找右边第一个比自己大(小)的数字的问题。从左到右遍历数组,利用单调栈找到每个员工右边第一个比自己大的数字。第二个员工(10)找不到比自己大的数字,奖金为 10。如果找不到比自己大的数字,则奖金为自己随机数字的数量。如果找不到比自己大的数字,则奖金为自己随机数字的数量。第三个员工(3)找不到比自己大的数字,奖金为 3。栈中存储员工的索引,确保栈中的数字是递减的。
2025-02-22 15:37:40
259
原创 List 接口中的 sort 和 forEach 方法
List 接口中的 sort 和 forEach 方法是 Java 8 引入的两个非常实用的函数,分别用于 排序 和 遍历 列表中的元素。super E> c:用于指定排序规则的比较器。如果为 null,则使用元素的自然顺序。默认使用自然顺序(如数字从小到大,字符串按字典序),也可以通过自定义比较器(Comparator)指定排序规则。这两个函数是 Java 8 引入的函数式编程特性的一部分,能够显著提高代码的简洁性和可读性。sort:用于排序,支持自然顺序和自定义比较器。对列表中的元素进行排序。
2025-02-21 14:22:51
467
原创 java模式与匹配类Pattern和Matcher类
它们提供了强大的正则表达式功能,用于字符串的匹配、查找、替换和分割等操作。String replaceFirst(String replacement) 将第一个匹配的子串替换为指定字符串。String replaceAll(String replacement) 将所有匹配的子串替换为指定字符串。提供了丰富的匹配操作方法(如 find()、matches()、group() 等)。boolean find() 查找输入字符串中是否存在与正则表达式匹配的子串。
2025-02-20 23:54:19
541
原创 算法题--运维日志排序
正则表达式 “(\d+)😦\d+)😦\d+)(?:\.(\d+))?使用 Integer.parseInt 提取时间部分,并计算总毫秒数。添加异常处理,确保输入格式错误时程序不会崩溃。:\.(\d+))?:可选匹配毫秒部分。(\d+):匹配小时、分钟、秒。改进1:增强正则表达式的健壮性。改进2:优化时间转换逻辑。改进3:增强代码可读性。
2025-02-20 23:13:36
489
原创 动态规划-力扣第300题“最长递增子序列”
*而不是dp[i] = dp[j] + 1;举个例子:27869,i=4,j=2时dp[j] = 3,j=3时dp[j] = 2。dp[j]后面是可能比前面大的,这样遍历前面得到的dp[i]是可能更大的,但是我们只取最大的就好了。如果 nums[j] < nums[i],说明 nums[i] 可以接在 nums[j] 后面,更新 dp[i] = max(dp[i], dp[j] + 1)。对于每个 i,遍历 j 从 0 到 i-1,如果 nums[j] < nums[i],则更新 dp[i]。
2025-02-19 21:19:23
326
原创 java数组转为字符串的几种方法
在 Java 中,将数组转换为字符串有多种方法,具体取决于数组的类型(如基本类型数组或对象数组)以及你希望输出的字符串格式。支持类型:基本类型数组(如 int[]、double[])和对象数组(如 String[])。适用场景:将字符串数组(String[])拼接为单个字符串,可指定分隔符。适用场景:将数组转换为字符串,格式为 [元素1, 元素2, …适用场景:将多维数组(如二维数组)转换为字符串。适用场景:利用流式操作将数组转换为字符串。支持类型:任意类型数组。支持类型:任意类型数组。
2025-02-19 17:50:42
248
原创 01背包算法-代表团坐车详解
用自然语言表达:当考虑接待当前代表团时,所有能承载 j 人的方案,都可以通过增加当前代表团扩展为承载 (j+group) 人的新方案。如果是正序遍历,当处理到较大的 j 值时,可能已经使用了当前代表团的信息,导致重复计数。状态独立性:确保 dp[j] 是未考虑当前代表团时的状态值。动态规划转移还可以写成:(更符合模版写法)物品 → 代表团(每个代表团只能选一次)新增一个载客量为 group 的代表团。该状态的方案数需要累加原状态的方案数。新的载客量状态 j + group。目标 → 恰好装满背包的方案数。
2025-02-19 11:16:40
133
原创 dp数组初始化
INF 是 Infinity(无穷大) 的缩写,在编程中通常用来表示一个极大或极小的值,具体取决于问题的需求。在动态规划中,INF 也常用于初始化 dp 数组,表示某个状态在初始时是不可达的或无效的。因此,初始化为 0 是动态规划中求最大值问题的常见做法,能够确保状态转移的正确性。在求最大值的问题中,-INF 表示一个极小的值,用于初始化 dp 数组。在求最大值的问题中,dp[j] 的值会从 0 开始逐步更新为更大的值。在求最小值的问题中,INF 表示一个极大的值,用于初始化 dp 数组。
2025-02-18 15:26:09
1264
原创 背包问题-01背包和完全背包
状态转移方程 dp[j] = max(dp[j], dp[j-w[i]] + v[i]) dp[j] = max(dp[j], dp[j-w[i]] + v[i])选:dp[i][j] = dp[i-1][j-w[i]] + v[i](前提是 j >= w[i])。选:dp[i][j] = dp[i][j-w[i]] + v[i](前提是 j >= w[i])。最小价值:dp[j] = min(dp[j], dp[j - w[i]] + v[i])。// 一维数组优化空间。// 一维数组优化空间。
2025-02-17 23:54:46
665
原创 力扣第416题“分割等和子集”
计算总和:首先计算数组的总和 sum,如果 sum 是奇数,那么肯定无法分割成两个和相等的子集,直接返回 false。给定一个只包含正整数的非空数组 nums,判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。dp[j - num] 表示是否可以从数组中选出一些数,使得它们的和等于 j - num。DP数组:dp[j] 表示是否可以从数组中选出一些数,使得它们的和等于 j。dp[j] 表示是否可以从数组中选出一些数,使得它们的和等于 j。空间复杂度:O(target),使用了一维数组 dp。
2025-02-17 18:24:12
170
原创 java Stream API中的聚合操作
聚合操作是对集合中的元素进行汇总、统计或计算的过程。通过Stream API,可以轻松实现各种聚合操作,如求和、求平均值、查找最大值/最小值、计数、分组、分区等。这些操作不仅代码简洁,而且支持并行处理,能够高效地处理大规模数据。
2025-02-16 20:31:22
941
原创 Stream API
Stream API是 Java 8 引入的一个强大工具,用于处理集合数据。它提供了一种声明式的方式来操作集合,支持链式调用和并行处理,使代码更简洁、易读。下面将详细介绍如何使用Stream API操作集合。
2025-02-16 20:26:17
707
原创 Java集合进阶
在Java中,集合框架(Collections Framework)是用于存储和操作一组对象的强大工具。它提供了多种接口和类,用于处理不同类型的集合(如列表、集合、队列、映射等)。为了帮助你学习Java集合的进阶知识,我将从以下几个方面进行讲解:Java集合框架主要包括以下接口和类:: 所有集合类的根接口。: 有序集合,允许重复元素(如 , )。: 无序集合,不允许重复元素(如 , )。: 队列,支持先进先出(FIFO)或优先级队列(如 )。: 键值对集合(如 , )。: 基于动态数组实现的列表。: 基于双
2025-02-16 15:56:01
922
原创 详解PriorityQueue
可以通过传递一个Comparator来实现最大堆。// 创建一个最大堆 PriorityQueue// 添加元素// 输出队列中的元素(按优先级顺序)while (!// 每次取出优先级最高的元素输出复制5321。
2025-02-16 15:52:41
1013
原创 Cannot run program “E:\software\java\bin\java.exe“ (in directory 找不到指定的文件夹
jdk配置
2024-11-17 22:13:40
930
1
springboot所有的测试类都需要加@SpringBootTest吗?
2021-07-25
springboot+mp,测试的时候遇到空指针异常
2021-07-23
TA创建的收藏夹 TA关注的收藏夹
TA关注的人