自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(65)
  • 收藏
  • 关注

原创 力扣hot100:搜索二维矩阵与在排序数组中查找元素的第一个和最后一个位置(74,34)

二分查找算法在有序数据中的高效应用 本文展示了两种使用二分查找算法解决有序数据结构问题的经典方法。第一种是二维矩阵搜索,通过两次二分(先定位行后定位列)将时间复杂度优化到O(logm + logn);第二种是查找目标值的范围,通过两次变种二分(分别找左右边界)高效确定首次和末次出现位置。两种方法都充分利用了数据的有序特性,通过调整搜索边界的方向,在O(logn)时间内完成搜索任务。文中详细分析了算法思路、边界处理技巧和实现细节,并提供了完整的代码示例,是掌握二分查找变种应用的优秀范例。

2025-08-23 20:42:22 681

原创 递归思路:从DFS到二叉树直径的实战(通俗易懂)

这篇文章总结了递归在解决二叉树最长路径问题中的应用。作者提出递归的四个关键点:问题分解、递归时机、边界条件和参数处理。通过LeetCode题解,展示了如何利用后序遍历自底向上计算子树深度,并在递归过程中动态更新最大直径值。核心思路是将问题分解为计算每个节点左右子树深度之和,使用全局变量记录最大值。该解法时间复杂度O(N),空间复杂度O(H),体现了递归"分而治之"的特点,适用于树形结构问题的求解。

2025-08-22 22:38:45 719

原创 项目中优惠券计算逻辑全解析(处理高并发)

本文介绍了优惠券计算系统的实现流程,主要分为五个步骤:1)查询用户可用优惠券;2)基于订单总价初步筛选优惠券;3)细化筛选可用课程并生成优惠券组合;4)并行计算各组合优惠明细;5)筛选最优方案。系统采用策略模式计算折扣,通过并行计算提高性能,并综合考虑优惠金额和用券数量选择最优方案,确保为用户提供最佳优惠体验。

2025-08-22 21:28:52 620

原创 力扣hot100:无重复字符的最长子串,找到字符串中所有字母异位词(滑动窗口算法讲解)(3,438)

本文摘要: 滑动窗口解决最长无重复子串问题: 使用双指针维护动态窗口,右指针扩展,左指针在发现重复时收缩 哈希集合实现O(1)重复检测 时间复杂度O(n),空间复杂度O(字符集大小) 滑动窗口寻找字母异位词: 通过比较字符频率判断异位词 固定长度窗口滑动,维护频率数组 时间复杂度O(n),空间复杂度O(1) 避免排序,直接比较频率提升效率 两种方法都利用滑动窗口优化时间复杂度,是处理字符串相关问题的有效技巧。

2025-08-21 23:27:23 1099

原创 深入解析HashMap的存储机制:扰动函数、哈希计算与索引定位

本文深入解析了Java HashMap的核心实现机制。HashMap通过哈希算法和索引定位实现高效键值对存储,关键步骤包括:1)扰动函数处理Key哈希值(高16位异或),减少碰撞;2)(n-1)&hash计算桶下标;3)根据碰撞情况存入数组/链表/红黑树。源码分析展示了Node结构、位与运算替代取模的效率优势,以及扰动函数必要性。最佳实践建议:合理实现hashCode(),根据预估元素数设置初始容量(取2的幂)。示例代码验证了从原始哈希到最终存储下标的完整计算过程。

2025-08-21 23:12:14 506

原创 list集合可以一边遍历一遍修改元素吗?

Java中List遍历时修改元素的注意事项:普通for循环可直接修改元素;foreach循环基于迭代器实现,受快速失败(Fail-Fast)机制约束,直接修改会抛出ConcurrentModificationException。关键机制涉及modCount(修改计数器)和expectedModCount(迭代器预期值),当二者不一致时触发异常。正确做法是使用迭代器的remove()方法,该方法会同步更新两个计数值。

2025-08-20 22:31:09 413

原创 力扣hot100:最大子数组和的两种高效方法:前缀和与Kadane算法(53)

本文介绍了解决最大子数组和问题的两种高效算法。前缀和法通过动态维护最小前缀和来求最大差值,时间复杂度O(n),空间复杂度O(1)。Kadane算法动态管理当前子数组和,当和为负时重置,同样具有线性复杂度。两种方法都能处理全负数数组,Kadane算法更简洁常用,而前缀和法更适用于需要复用前缀信息的场景。两种解法都体现了优化重复计算的核心思想,是解决子数组相关问题的经典范例。

2025-08-20 22:00:14 515

原创 力扣hot100:三数之和(排序 + 双指针法)(15)

摘要 本文提出了一种基于排序+双指针的高效算法来解决三数之和问题。首先对数组排序,然后固定一个数后转化为两数之和问题。通过双指针搜索匹配目标值,同时采用三重去重策略确保结果唯一性。算法时间复杂度O(n²),空间复杂度O(1)。关键点在于排序预处理、双指针移动策略和严格的去重处理,该方法可推广至N数之和类问题。

2025-08-19 21:48:17 422

原创 力扣hot100:找到字符串中所有字母异位词(滑动窗口 + 字符频率数组)(438)

本文提出了一种使用滑动窗口和字符频率数组高效解决字符串异位词匹配问题的方法。算法通过维护固定大小的窗口,动态统计字符频次,当窗口频次与目标字符串p完全一致时记录匹配位置。关键优化包括直接操作字符串而非转换列表,仅在窗口达标时进行频次比对。时间复杂度为O(n),空间复杂度O(1)。该方案通过滑动窗口机制有效减少了重复计算,适合处理字符串匹配类问题。

2025-08-19 21:38:56 283

原创 力扣hot100:盛最多水的容器:双指针法高效求解最大容量问题(11)

本文介绍了LeetCode第11题"盛最多水的容器"的双指针解法。问题核心在于计算由两条垂直线和x轴构成的容器能盛放的最大水量。解法使用双指针从数组两端向中间移动,每次移动较短线段的指针以寻找可能更大的容量。通过数学推导证明了该贪心策略的正确性,并给出了Java实现代码。文章分析了算法的时间复杂度为O(n),空间复杂度为O(1),指出这种双指针方法也适用于其他类似问题如两数之和、接雨水等。最后强调了双指针法在处理具有对称性的数组问题时的优势。

2025-08-18 21:24:29 378

原创 力扣hot100:移动零问题的巧妙解决:双指针与原地交换策略(283)

本文分享了LeetCode 283题"移动零"的高效解法,采用双指针交换法:快指针遍历数组寻找非零元素,慢指针标记非零元素应放置的位置。当快指针遇到非零时与慢指针位置交换,保证非零元素按顺序前移,零元素后移。解法时间复杂度O(n),空间复杂度O(1),仅一次遍历完成操作,保持元素原始顺序且原地操作。该思路适用于类似元素分类问题,展示了双指针在数组重排中的高效性。

2025-08-18 21:14:53 460

原创 Java基础Object中常见问题解析

Java基础复习摘要: ==与equals区别:==比较引用地址(对象)或值(基本类型);equals默认比较引用,可重写为内容比较(如String)。 hashCode与equals关系:若equals相等则hashCode必须相同,反之不成立,以支持哈希集合高效运作。 String/StringBuffer/StringBuilder: String不可变、线程安全; StringBuffer可变、线程安全(synchronized); StringBuilder可变、非线程安全但性能最优。 适用场景根

2025-08-17 23:07:18 1007

原创 微服务项目中MQ实战:解耦异步处理

本文介绍了消息队列(MQ)在在线教育平台中的应用实践。项目采用RabbitMQ实现系统解耦和异步处理,以点赞功能为例详细说明了MQ配置、常量定义、生产者和消费者实现。通过定义统一交换机和路由键,点赞服务将点赞事件异步发送至MQ,学习服务消费消息批量更新点赞数。这种方案实现了异步处理、服务解耦、消息可靠性和批量操作等优势,有效提升了系统性能和扩展性,同时保持了数据一致性。

2025-08-16 22:49:22 970

原创 深度剖析Redisson分布式锁项目实战

摘要:本文结合项目代码解析Redisson分布式锁的实现原理。通过自定义@MyLock注解实现AOP切面拦截,重点剖析了锁创建的两阶段过程:首先由锁工厂生成RLock代理对象(仅包含锁的元信息),实际加锁操作通过tryLock()方法触发,此时才会在Redis中创建对应的键值数据。文章详细说明了分布式锁的获取机制,包括键名冲突处理和等待机制,帮助开发者深入理解Redisson分布式锁的工作原理。

2025-08-16 22:30:48 308

原创 Redisson分布式锁实战指南:原理、用法与项目案例

Redisson分布式锁是解决分布式系统并发问题的有效工具,具备互斥性、防死锁、可重入和高性能等特点。文章介绍了SpringBoot整合Redisson的步骤,包括添加依赖、配置连接和使用核心API。通过高并发库存扣减案例展示了具体实现,强调锁续期、避免死锁等关键点。Redisson相比原生SETNX提供了更完善的解决方案,建议合理设置锁粒度、超时时间,并确保可靠解锁。该工具能有效解决分布式环境下的资源竞争问题。

2025-08-15 21:55:31 528

原创 锁失效,事务边界,事务失效在项目中的解决方案(补充)

文章摘要:本文探讨了并发控制中悲观锁与乐观锁的应用。重点分析了使用user.toString().intern()而非user.toString()作为锁对象的原因,前者通过字符串常量池确保同一用户请求获取相同锁对象。同时强调了"先上锁后开启事务"的正确顺序,避免因事务隔离级别导致的数据不一致问题。最后指出非事务方法调用事务方法会引发事务失效,建议通过获取代理对象的方式解决。这些知识点对处理高并发场景下的数据一致性问题具有重要实践意义。(149字)

2025-08-15 14:25:58 439

原创 悲观锁乐观锁与事务注解在项目实战中的应用场景及详细解析

摘要:本文探讨了在项目开发中运用悲观锁和事务注解解决并发问题的实践经验。通过优惠券抢购场景,分析了未加锁导致的超发问题和无事务引发的数据不一致问题。详细介绍了悲观锁实现(使用user.toString().intern())和事务边界处理,以及数据库层面乐观锁机制(通过条件判断保证数据一致性)。文章还预告将深入解释动态代理原理和事务与锁的边界问题。这些技术方案有效解决了高并发场景下的数据竞争问题。

2025-08-14 22:05:14 426

原创 反射在Spring IOC容器中的应用——动态创建Bean (补充)

本文介绍了利用反射机制实现动态方法调用的过程。通过读取配置文件中的类名和方法名,程序可以动态加载指定类并执行其方法。示例展示了TestInvoke类的三个方法(sayHello、sayBye、doWork),通过修改配置文件选择要调用的方法。核心步骤包括:获取Class对象、获取Method对象、创建实例并调用方法。这种反射机制使得程序能够在不修改代码的情况下,仅通过修改配置文件来切换执行不同的方法,体现了Spring IOC容器的灵活性。

2025-08-14 13:01:51 125

原创 Java Stream API 中常用方法复习及项目实战示例

本文总结了Java Stream流中map()和collect()方法的常见用法。map()用于元素转换,如将对象转为DTO;collect()用于收集结果,支持toList()、toSet()、toMap()和groupingBy()等操作。文中通过角色转换、优惠券统计等实例,展示了如何组合filter、map和collect实现数据筛选、分组和统计,突出了Stream API在数据处理中的简洁高效特性。

2025-08-13 22:01:07 438

原创 RedisTemplate 与 StringRedisTemplate 的区别

RedisTemplate与StringRedisTemplate的差异导致Redis数据查询失败。关键区别在于序列化方式:RedisTemplate采用二进制格式存储,而StringRedisTemplate使用字符串格式。当存储使用StringRedisTemplate而查询使用RedisTemplate时,由于序列化不匹配导致无法读取数据。建议处理字符串数据时优先选用StringRedisTemplate,以保证数据格式一致性和可读性。

2025-08-13 09:58:57 369

原创 xxl-job在实际项目开发中的应用步骤及解释

本文介绍了分布式任务调度框架XXL-Job的应用实践。XXL-Job是一款轻量级开源框架,适用于定时任务、批量处理、任务分片等场景。文章详细说明了其使用步骤:从依赖导入、配置类声明、Nacos公共配置到Spring Bean编写和任务注册。重点关注了如何通过注解方式实现任务调度,以及如何利用现有配置简化部署流程。通过具体案例展示了XXL-Job在解决分布式任务调度问题上的优势,为开发者提供了实用参考。

2025-08-12 15:15:33 403

原创 反射在Spring IOC容器中的应用——动态创建Bean

Spring IOC容器通过反射机制动态创建对象并管理依赖关系。文章以UserService和UserDao为例,详细解析了Spring容器的工作流程:1)解析XML配置文件获取Bean定义;2)使用Class.forName()加载类;3)通过getConstructor()获取构造器;4)利用newInstance()创建对象并注入依赖;5)将对象存入容器。这种反射机制避免了手动new对象,实现了控制反转,是Spring框架的核心特性之一。

2025-08-12 14:23:22 1098

原创 Java数据类型转换方法全面解析

本文系统总结了Java中的类型转换方法,包括基本数据类型转换(自动/强制)、包装类与基本类型转换(自动装箱拆箱)、字符串与其他类型互转(parseXxx/valueOf)、特殊类型转换(枚举/日期/进制)以及对象类型转换(向上/向下转型)。通过转换矩阵形式清晰展示了各类转换关系,强调使用标准JDK方法确保安全性和可靠性,并提供了数据溢出处理等实用技巧,帮助开发者编写健壮的代码。

2025-08-11 17:10:02 435

原创 Pipeline功能实现Redis批处理(项目批量查询点赞情况的应用)

本文介绍了使用Redis管道批量查询业务点赞状态的实现方法。通过executePipelined方法开启管道模式,将多个sIsMember命令缓存后批量执行,提高查询效率。代码中返回null是因为查询结果已自动存入List,最后通过流处理将点赞的业务ID收集为Set返回。该实现避免了多次网络请求,优化了Redis查询性能。

2025-08-06 19:45:57 442

原创 点赞服务完整消息流转过程详解(原方案,未使用Redis)

本文介绍了点赞功能的实现流程:用户点击点赞按钮后,前端发送POST请求到后端,Controller接收请求并调用服务层处理。服务层判断是点赞还是取消点赞,执行相应操作后统计最新点赞数,通过RabbitMQ发送消息。学习服务监听消息队列并更新数据库中的点赞数。整个流程采用消息队列实现服务解耦,具有异步处理、最终一致性、可靠性和扩展性等优势,确保了点赞数据的及时更新和系统的高效运行。

2025-08-06 19:04:07 930

原创 LeetCode 112. 路径总和解题思路详解(BFS算法深入理解)

本文介绍了使用BFS解决LeetCode 112题"路径总和"的算法。通过两个队列分别存储节点和路径和,在遍历时检查当前节点是否为叶子节点且路径和等于目标值。算法时间复杂度O(N),空间复杂度O(N)。文章详细解析了实现代码和示例执行流程,并指出双队列BFS解法的优点:逻辑清晰、易于扩展,强调必须同时满足路径和等于目标值且为叶子节点这个关键点。该解法是解决路径总和问题的经典方法。

2025-08-05 20:18:15 302

原创 实际项目开发中对消息队列(MQ)的使用详解

本文介绍了消息队列(MQ)在在线教育平台微服务架构中的应用实践。项目通过RabbitMQ实现了点赞业务的异步处理,包括:1)配置MQ依赖和共享参数;2)定义交换机、路由键等常量;3)生产者端发送点赞消息;4)消费者端批量更新点赞数。MQ的使用带来了异步处理、服务解耦、可靠性保障等优势,同时支持批量处理和系统扩展。项目还封装了MQ工具类简化操作,并强调在分布式系统中合理使用MQ可以构建高性能、高可用的服务架构。

2025-08-05 19:53:21 670

原创 力扣 70. 爬楼梯与121. 买卖股票的最佳时机:动态规划从入门到实战

本文解析了两道经典动态规划题目:70.爬楼梯和121.买卖股票的最佳时机。爬楼梯问题揭示了斐波那契数列的本质,通过滚动变量优化空间复杂度至O(1);股票问题则通过维护历史最低价和当前最大利润两个状态来求解。两题共同体现了动态规划的核心思想:将问题分解为重叠子问题,利用状态转移方程避免重复计算,时间复杂度均为O(n)。文章还给出了变种问题的解题思路,强调动态规划通过"记忆化"将指数问题降为多项式时间,是理解DP思想的入门基石。

2025-08-02 15:38:37 485

原创 动态规划解最长回文子串:深入解析与优化问题

本文探讨了使用动态规划解决最长回文子串问题的算法。通过构建二维数组标记子串状态,从单字符开始逐步扩展,利用首尾字符匹配和内部子串状态判断回文性。算法时间复杂度O(n²),空间复杂度O(n²),适用于中等规模字符串处理。文章详细解析了边界条件处理、状态转移方程和代码实现要点,并建议了空间优化方案和更高效的替代算法(中心扩展法、Manacher算法)。该解法展示了动态规划在字符串处理中的典型应用,强调了状态转移和边界处理的重要性。

2025-08-02 15:22:52 456

原创 Java Stream流处理技巧大揭秘

Java Stream API 实用方法总结 Java8引入的Stream API极大简化了集合数据处理,本文介绍几种常用方法: filter() 过滤元素 map() 转换元素 flatMap() 扁平化处理嵌套集合 distinct() 去重 sorted() 排序(支持自定义) limit()/skip() 限制元素数量 peek() 调试用中间操作 终端操作方法包括: collect() 收集结果到集合 reduce() 归约操作(求和/最大值等) count()/anyMatch()/findFi

2025-07-31 15:35:23 380

原创 MyBatis-Plus的LambdaQuery用法

MyBatis-Plus的LambdaQuery是一种类型安全的查询方式,通过Lambda表达式构建查询条件,避免字段名硬编码。核心优势包括编译器检查字段引用的类型安全、链式调用的高可读性,以及IDE自动更新的重构友好性。典型使用步骤包括创建Lambda查询包装器、链式构建条件(如eq/gt/like等)和执行查询。常用方法涵盖等值查询、模糊匹配、范围筛选、嵌套条件和字段选择等场景,支持动态条件避免if判断。虽然LambdaQuery简化了单表查询,但复杂SQL仍需XML/注解方式。该方式显著降低SQL拼接

2025-07-10 21:07:42 663

原创 MyBatis-Plus 中使用 Wrapper 自定义 SQL

MyBatis-Plus通过Wrapper自定义SQL实现动态条件查询,核心使用${ew.customSqlSegment}占位符注入条件。Mapper接口需用@Param("ew")声明Wrapper参数,XML/注解SQL中嵌入该占位符即可自动生成WHERE语句。支持QueryWrapper/LambdaQueryWrapper构建条件,注意字段名一致性。示例展示了单表查询、联表查询及Lambda表达式用法,强调防止SQL注入、处理表别名等注意事项。该方案兼顾MyBatis灵活性,简

2025-07-10 20:27:01 600 1

原创 MyBatis-Plus 条件构造器详解(QueryWrapper/LambdaQueryWrapper/UpdateWrapper/LambdaUpdateWrapper)

MyBatis-Plus条件构造器详解:提供了QueryWrapper(普通查询)、LambdaQueryWrapper(Lambda查询)、UpdateWrapper(更新操作)和LambdaUpdateWrapper(Lambda更新)四类核心构造器。Lambda变体通过方法引用确保字段安全,推荐优先使用。构造器支持字段选择、条件设置、排序等操作,可组合实体对象实现复杂更新。最佳实践建议:1)首选Lambda方式避免硬编码 2)混合使用实体设值和Wrapper条件 3)慎用字符串字段名。合理使用可显著减

2025-07-09 19:58:58 377

原创 苍穹外卖-微信登录部分笔记(下)

本文介绍了微信小程序用户登录的后端实现流程:1)小程序获取code发送至后端;2)后端通过code向微信服务器换取openid;3)查询数据库判断用户是否存在,不存在则新建用户;4)生成JWT token返回给前端;5)前端存储token用于后续请求认证。整个过程涉及微信登录凭证校验、用户数据存储和JWT令牌生成等关键步骤,为小程序用户身份认证提供了完整解决方案。

2025-05-31 23:30:00 446

原创 苍穹外卖-微信登录部分笔记(上)

微信小程序登录流程解析:通过wx.login获取临时code(5分钟有效),后端使用code换取用户唯一标识openid和会话密钥session_key。openid用于识别用户身份,session_key用于解密敏感数据(如手机号)。流程包括:前端传code给后端,后端调用微信接口获取用户信息,查询或注册用户,生成JWT token返回。该机制确保了用户身份的安全识别和数据传输保护。

2025-05-31 18:37:45 694

原创 Redis 集合、有序集合与通用命令详解

注:本篇为苍穹外卖学习笔记

2025-05-27 22:00:39 460

原创 Redis核心数据结构操作指南:字符串、哈希、列表详解

注:此为苍穹外卖学习笔记

2025-05-27 19:37:11 1145

原创 PageHelper分页原理解析:从源码到MySQL方言实现

本文深入解析了MyBatis生态中PageHelper插件(v5.3.2)的分页实现机制。通过MyBatis插件机制,PageHelper在SQL执行前拦截并动态改写SQL语句,实现物理分页。其核心设计包括:使用ThreadLocal存储分页上下文,支持多数据库方言,自动生成COUNT查询,并结合MySQL的LIMIT语法特性进行分页处理。文章详细阐述了从分页参数设置、SQL拦截、参数绑定到结果封装的完整执行流程,并提供了避免深分页、参数校验等最佳实践建议。理解PageHelper的实现原理有助于开发者更好

2025-05-22 20:12:29 755

原创 Java多线程实现——复习记录

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程/* 新建 */NEW ,/* 可运行状态 */RUNNABLE ,/* 阻塞状态 */BLOCKED ,/* 无限等待状态 */WAITING ,/* 计时等待 *//* 终止 */TERMINATED;// 获取当前线程的状态通过源码我们可以看到Java中的线程存在6种状态,每种线程状态的含义如下。

2025-05-18 22:05:05 708

原创 Java多线程实现——复习记录

生产者消费者模式是一种经典的多线程协作模式,通过生产者线程生产数据,消费者线程消费数据,两者通过共享数据区域进行解耦。生产者将数据放入共享区,消费者从中取出数据,双方无需直接交互。Java中通过wait()、notify()和notifyAll()方法实现线程的等待与唤醒。案例中,生产者(厨师)和消费者(吃货)通过共享的桌子(Desk类)进行交互,生产者生产汉堡包,消费者消费汉堡包,并通过锁机制确保线程安全。优化后的案例将共享数据封装在Desk类中,并通过阻塞队列(BlockingQueue)实现更高效的线

2025-05-18 22:01:01 916

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除