- 博客(65)
- 收藏
- 关注
原创 【从零理解 Spring AI · 03】Spring AI 在 Spring 生态里的位置
写完前两篇的概念铺垫,有性子急的朋友问我:概念我大概懂了,但我现在就能用 `RestClient` 发个 POST、拼个 JSON 把模型调通,**为什么还要引入一个框架?**
2026-11-05 23:46:18
275
原创 【从零理解 Spring AI · 02】大模型为什么“记不住“也“不知道“
上一篇结尾我留了一个悬念:模型的三个边界,决定了 AI 应用的三套机制。
2026-11-05 23:46:11
143
原创 【从零理解 Spring AI · 01】AI 应用开发,Java 工程师该先搞清楚哪几件事
这个专栏是我想搞清楚一件事:**用 Java 做 AI 应用,到底和平时写业务代码有什么不一样。**
2026-11-05 23:46:02
102
原创 排序(4)-归并排序专题——归并排序的分治美学
无论数组初始状态如何,归并排序的递归树层数都是 \log n,每层合并的开销都是 O(n)。因此,它的最好、最坏、平均时间复杂度全都是严格的。找到数组的中点,将其一分为二。递归地对左半部分和右半部分继续切分,直到子数组的长度为 1(长度为 1 的数组天然有序)。由于在合并阶段需要和原数组等长的辅助数组来暂存元素,这是它相比于快排和堆排序最大的劣势(空间换时间)。将两个已经有序的子数组合并成一个更大的、完全有序的数组。在这个过程中需要一个辅助数组来暂存数据。),就能完美保持相同元素的相对顺序。
2026-06-11 01:58:44
241
原创 排序(3)-第三篇:交换排序专题——从冒泡排序到快速排序的效率飞跃
从左到开依次比较相邻的两个数,如果前面的数比后面的大,就交换它们。这样一轮下来,当前区间的最大值就像“气泡”一样浮到了数组的最右端。,通过选择一个“基准值”,让大小元素横跨大半个数组进行对调,从而实现大步流星的排序。通过双指针左右开弓,把比 Pivot 小的扔到左边,比 Pivot 大的扔到右边。此时 Pivot 已经锁定了它的最终位置。这一族群里有两个极具代表性的选手:一个是无数人的启蒙算法——另一个则是工业界、面试官长盛不衰的宠儿——它们之间,是一场关于执行效率的惊艳飞跃。两个元素的无序问题。
2026-06-11 01:56:11
276
原创 排序(2)-选择排序专题——简单选择排序与堆排序的结构优化
构建初始堆耗时 O(n),执行 n 次交换和下沉调整耗时 O(n \log n)。将剩余的 n-1 个元素重新调整为大顶堆,再次将堆顶与倒数第二个元素交换。出发,看它如何借助“二叉堆”这一高效的数据结构,华丽蜕变为工业级的高性能算法——遍历结束后,将这个最小元素与未排序区的第一个元素进行交换(使其加入已排序区)。在每一轮选拔中,最直观的策略就是“统览全局,挑出最优”。在下沉和交换过程中,长距离的跨越会打乱相同元素的相对位置。每次遍历未排序区,记录下其中最小(或最大)元素的索引。,在第一轮选择中,第一位的。
2026-06-11 01:50:15
236
原创 排序(1)-插入排序专题——直接插入排序与希尔排序的递进艺术
使用希尔建议的减半序列,平均时间复杂度约为 O(n^{1.3}) 到 O(n^2) 之间。在日常生活中,我们打扑克牌时,往往会一边摸牌一边把牌插入到合适的位置,让手牌始终保持有序。因为此时数组已经接近完美有序,直接插入排序能跑出接近 O(n) 的极致性能!因为在不同的子序列之间发生跨距离交换,相同元素的相对顺序可能会被颠倒。扫描,比目标大的元素全部往后挪一步,直到找到它的合适位置安放。,以及它如何华丽蜕变为突破 $O(n^2)$ 瓶颈的。时,整个数组其实已经“基本有序”了。O(1),属于原地排序。
2026-06-11 00:28:18
598
原创 玩转 LeetCode Hot 100:滑动窗口两大万能解题模板与深度拆解
拿到一道连续子数组/子串的题目,如何迅速破局?关键词识别:只要题目中出现“连续子数组”“连续子串”“最长/最短满足...的区间”,不要犹豫,90% 概率掏出滑动窗口。判断窗口类型题目要求“最长/最短是多少”,套用模板一(可变窗口)。核心去想:什么时候该让左指针收缩?题目要求“长度必须等于固定值,套用模板二(固定窗口)。核心去想:怎么在保持的前提下,让左右指针一起往前蠕动?状态监控器的选择字符范围有限(如纯小写字母或 ASCII 码),优先用int[]数组作为窗口的状态记录器,性能最高。
2026-06-09 01:53:37
245
原创 玩转 LeetCode Hot 100:双指针两大万能解题模板与深度拆解
拿到一道题,怎么判定用哪种双指针?看数组是否有序 / 能否排序如果数组是有序的,或者要求找满足某个数值关系的组合(如两数、三数之和、盛水容器)优先考虑模板一:左右夹逼指针。如果数组是无序的,且要求原地修改数组、删除特定元素、或者是在链表中(如判断环、找中点)优先考虑模板二:快慢同向指针。消灭无意义的嵌套:只要看到题目需要“通过两层循环不断比对两两元素”,就可以用两个指针对省掉一层for循环,将空间复杂度锁死在 O(1)。
2026-06-05 02:08:23
397
原创 玩转 LeetCode Hot 100:哈希表两大万能解题模板与深度拆解
题目要我干什么?要我分门别类 / 算频次套用模板一。想一想什么可以当做划分格子的“特征(Key)”。要我找配对 / 找组合套用模板二。想一想当前元素的“另一半(Complement)”是谁,怎么去历史记录里捞它。消灭双层循环:只要发现自己写了两个for循环嵌套,就立刻引入一个Map或Set,用 O(1) 的查找把内层循环替代掉。
2026-06-04 03:11:55
466
原创 认识多线程:定时器
定时器的核心是「延时 / 周期性执行任务」,本质是多线程异步调度的应用。实际开发中,优先使用ScheduledExecutorService(线程池实现),避免使用Timer(单线程、异常崩溃问题)。优先级队列(任务排序)+ 线程阻塞(避免空轮询)+ 线程安全(锁机制)。进阶方向:可基于手动实现的版本,扩展线程池、周期性任务、异常重试等功能,更贴近生产环境需求。
2026-06-04 02:35:15
559
原创 MySQL中GROUP_CONCAT函数详解 | 按日期分组拼接销售产品经典案例
在日常的SQL业务开发中,我们经常遇到分组统计+分组内字段拼接的需求,比如按日期统计每日销售的产品数量、并将当日销售的所有产品名称拼接成一个字符串展示。这类需求用普通的GROUP BY分组+聚合函数是无法实现的,而MySQL的函数就是专门解决这类场景的「神器」,今天结合经典的「按日期分组统计销售产品」SQL案例,彻底吃透的用法和核心细节。是MySQL专属的分组聚合函数将分组后的同一组内的指定字段的所有值,拼接成一个完整的字符串返回。如果需要在分组内,拼接「产品名+价格」这类多个字段的组合值,可以嵌套。
2026-01-20 00:51:27
838
原创 MySQL字符串操作核心函数总结:从基础到实战
解决方案:用 ifnull(name, ‘’) 过滤NULL,或直接使用 concat_ws(‘’, upper(substring(name,1,1)), lower(substring(name,2)));需注意:中文场景下,substring 按字节截取,UTF-8编码中1个中文占3字节,直接截取可能乱码,需配合编码转换或专用函数。例题中,upper(substring(name,1,1)) 将首字符转为大写,lower(substring(name,2)) 将剩余字符转为小写,确保姓名格式统一。
2026-01-15 01:11:26
717
原创 数据结构之堆:从概念到应用全解析(附TOP-K经典问题)
相较于全量排序的O(nlogn),当k远小于n时(如k=10,n=10⁶),堆的解法效率优势极为明显,且适合海量数据(无需加载全部数据,逐批处理即可)。若子节点值更大,则交换父子节点;堆的核心是元素间的大小比较,在Java中,常用的三种比较方式分别是Object.equals、Comparable.compareTo、Comparator.compare,三者适用场景不同,在堆中主要用于定义元素的堆序性。原理:小根堆的堆顶是堆中最小的元素,通过不断淘汰比当前元素小的堆顶,最终堆中留存的就是最大的k个元素。
2026-01-08 02:10:31
1105
原创 数据结构之树与二叉树:重点梳理与拓展
同时,所有节点的边数之和为n-1(树的边数=节点数-1),而边数也等于n1* 1 + n2* 2(度为1的节点贡献1条边,度为2的贡献2条),联立可得n0 = n2 + 1。左孩子为5,右孩子为6(若n>6)。size():统计节点总数:递归实现,根节点为1,加上左子树节点数和右子树节点数,即size(root) = 1 + size(root.left) + size(root.right)(空节点返回0)。比如深度为3的满二叉树,总节点数为7(1+2+4),符合“深度为k的二叉树最大节点数”的规律。
2026-01-06 18:52:34
1043
原创 【AI进阶】拒绝“人工智障”:掌握提示词工程(Prompt Engineering)的6大核心技巧
同一个模型,在不同人手里,效果天差地别。有人能用它写出高质量的代码和研报,有人却只能得到废话连篇的回答。这其中的关键变量,就是提示词(Prompt)。提示词工程(Prompt Engineering)不仅仅是“说话”,它更像是一种自然语言编程。如何让AI精准理解你的意图?如何挖掘模型的最大潜力?本文将基于实战经验,为你总结6大核心技巧,助你从“随便问问”进阶为“提示词专家”。Zero-Shot(无样本)用户输入:“这手机一般般。” -> AI回答:“这句话表达了中立的情感。”(格式不可控)
2025-12-22 00:04:01
975
原创 从一题了解 CROSS JOIN 与 DATEDIFF:SQL 天气温度对比实战
同表不同行对比 → 用自连接(将表视为两张独立表);日期差值计算 → 用DATEDIFF(根据数据库选择对应语法);等同于INNER JOIN,核心是通过条件筛选有效配对。这类“对比相邻记录”的场景在实际业务中非常常见(如环比增长、连续登录判断等),掌握自连接和日期函数的组合用法,能轻松应对这类问题。建议大家多尝试修改条件(如查询温度比后一天高的记录、计算连续 2 天升温的 id),加深对知识点的理解~
2025-11-05 23:14:52
960
原创 认识多线程:单例模式
单例模式的两种实现(饿汉模式简单安全,懒汉模式需双重检查+volatile保证线程安全)阻塞队列的特性及生产者消费者模型(解耦+削峰填谷的关键工具)阻塞队列的手动实现(基于锁和条件变量的经典并发编程实践)掌握这些基础知识,是深入学习多线程编程的基础。实际开发中,JDK提供了丰富的并发工具类(如等),理解其底层原理能帮助我们更好地运用它们解决实际问题。
2025-11-02 16:46:50
424
原创 认识多线程:初阶基础知识之等待 / 通知机制
wait()notify()是线程间协作的核心方法,必须在代码块 / 方法中使用,且依赖对象锁。wait()释放锁并进入等待,notify()唤醒一个等待线程,唤醒所有等待线程。wait()与sleep()的核心区别在于是否释放锁和使用场景,面试中需重点区分。掌握这些基础后,就能更好地理解多线程协作模型(如生产者 - 消费者),为进阶学习打下基础。如果有疑问或补充,欢迎在评论区交流!
2025-11-02 01:54:40
334
原创 初识多线程(线程的状态与线程安全)
线程状态中BLOCKEDWAITING的区别。线程安全的本质是多线程对共享数据的并发修改,根源在于线程调度的随机性,辅以原子性、可见性、有序性问题。(保证原子性、可见性、有序性)和volatile(保证可见性、有序性)。标准库中线程安全类的特点及使用场景。多线程编程的核心是"控制并发",理解线程安全的本质和解决方案,是编写可靠并发程序的基础。
2025-11-02 00:04:36
852
原创 初识多线程:Java多线程初阶基础知识
线程(Thread)是进程中的一个执行单元,是操作系统进行调度的最小单位。一个进程可以包含多个线程,这些线程共享进程的资源(如内存空间、文件描述符等),但各自拥有独立的程序计数器、栈空间和局部变量。本文介绍了Java多线程的基础知识,包括线程与进程的区别、线程的五种创建方式、Thread类的构造方法与属性、线程的启动与中断、等待线程、获取当前线程及线程休眠等内容。多线程是Java编程中的重要知识点,掌握基础后还需深入学习线程同步(如Lock)、线程池、并发容器等进阶内容。
2025-11-01 13:51:42
643
原创 栈与队列深度解析:概念、实现与应用
/ 存储元素的数组// 栈中有效元素个数// 构造方法:初始化数组容量为3// 压栈操作// 检查容量,不足则扩容return e;// 出栈操作// 栈空则抛异常throw new RuntimeException("栈为空,无法执行出栈操作");size--;// 直接通过size减少实现“删除”(后续元素会覆盖)// 获取栈顶元素throw new RuntimeException("栈为空,无法获取栈顶元素");// 获取元素个数// 判断栈是否为空。
2025-10-10 00:58:56
434
原创 深入理解ArrayList与LinkedList:Java集合框架核心对比(含实战案例+面试考点)
线性表是n个相同类型数据元素的有限序列,逻辑上呈“连续直线”结构,比如数组、链表都属于线性表。用ArrayList:频繁随机访问(查多改少)、元素数量稳定;用LinkedList:频繁头尾插入/删除、需实现栈/队列;不确定时:优先用ArrayList(日常开发中“查”比“改”更频繁)。2倍扩容可能导致后续扩容时,旧数组无法被复用(比如容量100扩到200,只用101个元素,浪费99个,且旧数组占内存);1.5倍扩容更易触发内存回收,减少碎片。ArrayList和LinkedList。
2025-10-04 21:40:38
1603
原创 Java 集合框架之 List 全面解析(从概念到实践)
接口特性:List 是有序、可重复的线性表接口,继承自Collection。核心操作:支持通过下标进行增删改查,提供子列表视图等工具方法。实现类选择ArrayList适合查询,LinkedList适合频繁增删。下期将深入分析ArrayList与LinkedList的底层实现及性能差异。
2025-10-01 23:19:51
660
原创 时间复杂度与空间复杂度知识框架
衡量算法效率的两个核心维度是时间复杂度和空间复杂度。时间效率反映算法执行速度,空间效率反映算法对存储资源的消耗。随着硬件存储容量的提升,现代算法设计更注重时间效率优化。斐波那契数列递归算法是典型例子,其时间效率低下(指数级复杂度),凸显复杂度分析的必要性。
2025-10-01 15:49:24
258
原创 Java 异常全方位解析:从基础到实战的完整指南
定义:程序运行时偏离预期的非正常情况(如空指针、数组越界)与错误(Error)的区别:异常可处理,错误(如 OOM)通常无法恢复生活类比:用 “开车遇到爆胎(异常,可修复)” 和 “发动机报废(错误,无法修复)” 辅助理解场景:业务错误需要区分(如 “用户不存在异常”“余额不足异常”)实现步骤:继承 Exception(受检)或 RuntimeException(非受检)实现无参、带消息、带 cause 的构造方法代码示例:自定义业务异常。
2025-09-23 01:29:35
1013
原创 String的使用:从基础到透彻
实现(JDK 8),修改操作实际生成新对象。关键点标注参数范围规则(左闭右开),避免读者误用。方法讲解需包含功能说明、代码示例与注意事项。
2025-09-23 01:20:26
461
原创 MySQL DENSE_RANK () 窗口函数:一篇搞懂连续排名用法
DENSE_RANK() 是 MySQL 窗口函数,用于计算连续排名,遇到并列值时不会跳过后续排名。例如,两个分数相同的记录并列第 1,下一条记录直接排第 2,而非第 3。关键点:需求:对数学成绩降序排名,不分组。结果示例:需求:按科目分组,组内分数降序排名。结果特点:需求:同科目同分数时,按学生 ID 升序排序。结果示例:语文 92 分的记录中,ID 小的学生排在前面,但排名仍为 1。区别总结:
2025-08-23 21:57:22
906
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅