加载中

Java

文章分类

浏览该分类下的所有文章

237 篇文章 20

哈希

hashCode() 与 equals() 是 HashMap 正确定位键值对的核心,若实现不当会导致冲突或误判相等,进而影响集合的精确性。HashMap 以键的 hash 值确定桶位置,JDK 7 采用数组+链表(头插),JDK 8 在链表长度超过阈值时转为红黑树(尾插),容量默认 16,扩容为 2ⁿ 幂,受初始容量和负载因子(默认 0.75)控制。HashMap 不是同步的、键值可为 null,且不保证有序。构造一致性哈希时先在 2³² 环上布置节点,再根据键的 hash 顺时针定位最近节点,以提升扩缩容时的命中率。作为键的对象必须保证 hashCode 在生命周期内不变。HashSet 基于 HashMap 实现,存储的元素是无序的。

TreeMap/TreeSet在排序时要求元素实现Comparable的compareTo或在构造时提供Comparator;Collections.sort同样支持Comparable或Comparator 两种重载,实现元素比较的回调机制。文中给出Student实现Comparable并在TreeSet中按年龄升序去重的示例。随后介绍二叉树的常见算法:层序遍历(使用队列返回数组或分层列表并换行)、递归与非递归求树深度、利用层次遍历统计最大路径长度。最后简述B+树与B‑树的区别:B+树内部节点不存数据、叶子链表支持区间查询、适合外部存储;B‑树键值同存,查询复杂度受键位置影响。

遍历

本文展示了两种遍历实现示例。第一段给出二叉树之Z字形层序遍历的Java代码,利用队列按层遍历并通过标记奇偶层在偶数层逆序输出,从而实现 ZigZag 顺序。第二段实现文件系统的递归遍历:通过File.listFiles()获取目录内容,若为文件则打印名称,若为子目录则递归调用,实现对指定文件夹及其所有子文件夹中文件的完整遍历。两段代码均强调了遍历的基本思路与实现细节。

链表

本文围绕单向链表的常考算法展开。首先介绍快慢指针法判断链表是否成环:快指针两步、慢指针一步,若相遇则有环,否则至NULL即无环。随后指出在哈希桶中使用链表存储的缺点——查找、插入、删除均需遍历,效率低下。接着给出一种将“奇数位升序、偶数位降序”链表转为整体升序的思路:按奇偶位拆分成两条链表、将偶数位链表逆序再与奇数位链表合并,配以完整的Java实现。随后展示复制含随机指针的链表的 O(1) 额外空间算法(插入复制节点、复制 random 指针、拆分两表)。最后给出单链表就地反转的标准写法。全文重点在于链表的环检测、性能缺陷、分割合并排序以及复制与反转的实现细节。

数组

本文列举了若干常见的数组算法面试题及其实现思路。包括:① 将 N×N 矩阵顺时针旋转 90°,通过层层交换四边元素实现;② 在除一个元素外其余均成对出现的数组中找出唯一元素,使用异或运算;③ 求数组中任意一对和为给定 S 的数,利用哈希表在一次遍历中定位;④ 求连续子数组的最大和,采用 Kadane 算法在线性时间内完成;⑤ 查找数组前 K 大的数,采用快速选择(基于快排划分)实现。每个题目均给出对应的 Java 代码示例,突出考察点在数组的遍历、哈希、位运算和分治技巧。

排序

文章展示了Java实现的冒泡排序并给出输出示例,列举常见排序算法(插入、交换、选择、归并、分配),简述归并排序的分治合并过程和堆排序的建堆、调整、排序步骤。随后说明在数据流中用最大堆和最小堆维护左右两侧数据,可在 O(log n) 插入、O(1) 获取中位数。最后简要介绍快速排序的左右指针划分与交换机制,并提及各算法的时间复杂度。

堆与栈

本文阐述了 Java 内存模型中的三大区域——堆、栈和方法区(静态区)的作用与特点。堆是所有线程共享的对象实例存储区,由程序员通过 new 分配,垃圾回收自动释放;栈为每个线程私有,仅保存基本类型变量和对象引用,空间由系统自动分配回收,遵循后进先出原则;方法区同堆共享,保存类信息、static 变量等全局唯一数据。文中进一步比较了堆与栈的分配方式、容量、访问速度及生命周期差异,并通过示例说明两者在实际代码中的表现。

队列

PriorityQueue 是基于堆实现的无界队列,元素按自然顺序或自定义比较器排序,不接受 null,非线程安全,入队和出队的时间复杂度均为 O(log n)。

高级算法

本文围绕面试常见的高级算法问题提供概念与实现要点。首先阐述LRU(最近最少使用)缓存的原理:依据局部性原理,淘汰最近最久未被访问的页面,核心操作为 get(key) 与 put(key,value),实现简单但命中率受批量访问影响。随后简要说明逆波兰(后缀)表达式无需括号的优势、基于 MD5 的 URL 短链生成思路、以及 SnowFlake 分布式全局唯一自增 ID 的 64 位结构与优缺点。最后给出 LFU(最不常用)缓存的 O(1) 设计思路,使用双向链表按访问频率分层并配合哈希表实现快速 get 与 put。整体呈现了几类典型缓存与分布式 ID 算法的核心概念、实现关键及适用场景。

设计模式

本文阐述了面向对象设计的六大原则——单一职责、里氏替换、依赖倒置、接口隔离、迪米特法则和开闭原则,强调它们在提升代码高内聚、低耦合、可复用、可维护和可扩展方面的作用。重点说明开闭原则要求模块对扩展开放、对修改关闭,并通过实例说明其对复用、维护、灵活性和测试的益处。随后给出单例模式的饿汉、懒汉以及线程安全实现代码示例。最后介绍工厂模式的概念,分别解释了简单工厂和工厂方法的实现思路与适用场景。

场景题

本文围绕五大实战场景展开概述:① 微信红包采用实时内存计算、随机分配算法及 Redis‑Cache 计数,保证高并发下的金额准确与防超额;② 秒杀系统重点解决超卖、高并发、接口防刷等问题,提出独立库存库、动态 URL、页面静态化、Redis 集群预减库存、限流、异步下单与服务降级等方案;③ 二维码扫码登录基于 token 与一次性凭证的三阶段流程(待扫描、已扫待确认、已确认),实现跨终端安全登录;④ 单点登录(SSO)通过统一认证中心、令牌传递、全局/局部会话及统一注销,实现多系统免密访问;⑤ 本地缓存设计关注存储结构、容量上限、LRU/FIFO 等淘汰策略、过期机制及线程安全。整体阐释了高并发业务的架构思路与实现细节。

UML

UML提供多种图形化符号来描述系统的静态和动态结构,包括用例图、类图、时序图、协作图、状态图、活动图、构件图和部署图等。其中,用例图用于捕获需求,展示系统功能模块及其关系;类图描述类及类间关联,帮助快速了解系统结构;时序图呈现对象在执行任务时的交互顺序,揭示对象可提供的服务。这三类图是UML中最核心的视图。