news 2026/10/27 1:17:44

Java代码优化心得

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java代码优化心得

性能优化不是玄学,也不是只有资深架构师才需要关心的事。日常写业务代码时,一个数据结构选错、一次循环里的重复计算、一段用异常控制流程的逻辑,都可能在高并发或大数据量下被放大成明显的性能瓶颈。本文聚焦 Java 性能优化中最容易落地、收益也最直接的 5 个实用技巧:优化算法与数据结构、减少对象创建、优化循环内的代码、合理使用异常处理、能用批量操作就不要用 for 循环。每一条都会说明适用场景并给出可直接运行的示例代码,帮助你在实际项目中快速判断「这里该不该优化、该怎么优化」。

1. 优化算法与数据结构

  • 方案:根据业务场景选择合适的算法和数据结构,能显著提升代码性能。例如,若需要频繁进行随机访问,可选用ArrayList;若要进行高效的查找操作,HashMap是常用的选择。
  • 关于LinkedList的常见误区:很多资料说「频繁插入删除就用LinkedList」,这并不严谨。LinkedList每个节点都有额外的对象头和前后指针开销,且内存不连续、缓存不友好,在随机位置插入删除时往往并不比ArrayList快。只有在已知节点位置(如持有ListIterator)或频繁在头尾操作时,它才有优势。绝大多数业务场景下,ArrayList是更稳妥的默认选择。
  • 实例:假设要统计一个字符串中每个字符的出现次数。可以使用HashMap来实现:
importjava.util.HashMap;importjava.util.Map;publicclassCharacterCount{publicstaticvoidmain(String[]args){Stringstr="hello world";Map<Character,Integer>charCountMap=newHashMap<>();for(charc:str.toCharArray()){charCountMap.put(c,charCountMap.getOrDefault(c,0)+1);}System.out.println(charCountMap);}}

2. 减少对象创建

  • 方案:对象的创建和销毁会消耗系统资源,应尽量减少不必要的对象创建。可以使用对象池技术,或者重用已有的对象。
  • 实例:在字符串拼接时,若拼接次数较多,使用StringBuilder代替String。因为String是不可变对象,每次拼接都会创建新的对象,而StringBuilder是可变的,能避免频繁创建对象。
    publicclassStringConcatenation{publicstaticvoidmain(String[]args){StringBuildersb=newStringBuilder();for(inti=0;i<1000;i++){sb.append(i);}Stringresult=sb.toString();System.out.println(result);}}

3. 优化循环内的代码

  • 方案:真正有效的循环优化,是消除循环体内的重复计算、避免在循环内做 I/O 或加锁、减少自动装箱与临时对象创建。至于「提前把array.length提到循环外」,在现代 JVM 上 JIT 基本会优化掉,收益极小,不必刻意为之。
  • 实例:下面这段代码在循环内反复调用map.get、反复做字符串拼接和自动装箱,是典型的可优化点:
importjava.util.HashMap;importjava.util.Map;publicclassLoopOptimization{publicstaticvoidmain(String[]args){Map<String,Integer>priceMap=newHashMap<>();priceMap.put("apple",5);priceMap.put("banana",3);String[]items={"apple","banana","apple"};// 优化前:循环内重复查表 + 字符串拼接产生临时对象Stringbad="";for(inti=0;i<items.length;i++){bad+=items[i]+"="+priceMap.get(items[i])+";";}// 优化后:查表结果复用,拼接改用 StringBuilderStringBuildersb=newStringBuilder();for(Stringitem:items){Integerprice=priceMap.get(item);if(price!=null){sb.append(item).append('=').append(price).append(';');}}System.out.println(bad);System.out.println(sb);}}
  • 适用场景:循环次数大(上万次以上)、循环体内有查表/字符串拼接/自动装箱/日志拼接等操作时,收益最明显;循环体本身只是一次简单加法时,不必过度改造。

4. 合理使用异常处理

  • 方案:异常处理会带来一定的性能开销(构造异常对象需要填充栈信息),应避免在频繁调用的方法中用异常来控制正常流程。可以用条件判断或字符遍历来替代。
  • 实例:判断一个字符串是否为整数时,用try/catch NumberFormatException虽然写法简单,但在大量非法输入的场景下会频繁抛异常,开销明显。改用字符遍历判断更稳妥:
publicclassNumberCheck{// 方式一:靠异常判断,非法输入多时开销大publicstaticbooleanisNumberByException(Stringstr){if(str==null||str.isEmpty()){returnfalse;}try{Integer.parseInt(str);returntrue;}catch(NumberFormatExceptione){returnfalse;}}// 方式二:字符遍历判断,无异常开销,且能明确处理正负号publicstaticbooleanisNumberByScan(Stringstr){if(str==null||str.isEmpty()){returnfalse;}intstart=0;if(str.charAt(0)=='-'||str.charAt(0)=='+'){if(str.length()==1){returnfalse;}start=1;}for(inti=start;i<str.length();i++){if(!Character.isDigit(str.charAt(i))){returnfalse;}}returntrue;}publicstaticvoidmain(String[]args){System.out.println(isNumberByException("123"));System.out.println(isNumberByScan("-123"));System.out.println(isNumberByScan("12a"));}}
  • 适用场景:输入以合法值为主时,try/catch写法更简洁,性能也可接受;输入中非法值占比高、或该方法处于高频调用路径上时,优先用字符遍历等无异常方案。注意正则表达式本身开销也不小,且\d+不覆盖负数、小数和空白,不适合作为「替代异常」的通用方案。

5. 可以批量操作的,不要用for循环

  • 方案:这里的重点不是「禁用 for 循环」,而是减少与数据库等外部资源的往返次数。当需要执行大量同类型的 SQL 时,用 JDBC 批量接口(addBatch/executeBatch)把多条语句合并成一次网络交互,性能提升非常明显。
  • 实例:批量插入 1000 条记录,逐条执行与批量执行的对比:
importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;publicclassBatchInsertDemo{privatestaticfinalStringSQL="INSERT INTO user (id, name) VALUES (?, ?)";// 逐条执行:1000 次网络往返publicstaticvoidinsertOneByOne(Connectionconn)throwsException{try(PreparedStatementps=conn.prepareStatement(SQL)){for(inti=0;i<1000;i++){ps.setInt(1,i);ps.setString(2,"user"+i);ps.executeUpdate();}}}// 批量执行:攒够一批再提交,大幅减少往返次数publicstaticvoidinsertBatch(Connectionconn)throwsException{try(PreparedStatementps=conn.prepareStatement(SQL)){for(inti=0;i<1000;i++){ps.setInt(1,i);ps.setString(2,"user"+i);ps.addBatch();if(i%500==0){ps.executeBatch();}}ps.executeBatch();}}publicstaticvoidmain(String[]args)throwsException{try(Connectionconn=DriverManager.getConnection("jdbc:mysql://localhost:3306/demo","root","123456")){insertBatch(conn);}}}
  • 适用场景:批量插入、批量更新、批量删除等写操作收益最大;批量大小建议控制在几百到几千条,过大反而会增加内存占用和单次事务时长,具体需结合数据库与网络情况压测确定。

总结

这 5 条建议本质上都指向同一个目标:减少不必要的开销。选对算法与数据结构,是从源头降低时间与空间复杂度;减少对象创建,是减轻 GC 压力;优化循环内代码,是消除重复计算;合理使用异常处理,是避免把异常当作流程控制;批量操作替代 for 循环,则是减少与数据库等外部资源的交互次数。

从实践优先级来看,建议按以下顺序推进:

  1. 先做算法与数据结构层面的优化:收益最大、改动成本相对可控,往往能带来数量级的提升,应作为首选。
  2. 其次关注批量操作与循环优化:这两类问题在数据量增大时放大效应明显,且改造方式清晰,容易落地。
  3. 再次是减少对象创建:在热点路径上收益显著,但需要结合对象池、StringBuilder等手段谨慎使用,避免过度设计。
  4. 最后是异常处理规范:更多属于编码习惯层面的改进,单次收益有限,但长期坚持能避免隐性性能损耗。

需要强调的是,优化前应先通过压测、火焰图或 APM 工具定位真正的瓶颈,避免凭直觉「过早优化」。先让代码正确、清晰,再让它在关键路径上足够快。

另外,性能结论对运行环境依赖很强,本文示例基于JDK 17、默认 JVM 参数、MySQL 8.0 编写。不同 JDK 版本(尤其是 JIT 优化策略的变化)和不同硬件下,实际收益可能有差异,建议在自己的环境中用 JMH 或简单计时做一次对比验证,再决定是否改造。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 1:16:53

[UVM笔记]UVM 保存mem

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/27 1:16:50

课件---程序设计基础-第5章- 选择控制结构--if else

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/27 1:15:23

【GATT】规范精讲[6]: 写得进去还要写得靠谱——五种写过程、签名写、可靠写与写描述符

读过程解决的是把值拿回来,方向是服务器流向客户端;这一篇把方向倒过来:客户端把值写进服务器。表面看就是换个 PDU 的事,真写起来会发现写比读麻烦得多。读失败了大不了重试,数据还是对端那份;写一旦在半路上出岔子,配置可能改了一半、固件可能写花、设备可能变砖。所以…

作者头像 李华
网站建设 2026/10/27 1:14:38

Verilog基础:操作数的位选(bit-select)和域选(part select)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 位选 位选(bit-select)用于选择一个向量(vector)的某位&#xff0c;可以是线网大类(net)&#xff0c;也可以是变量大类(variable)中的reg、integer和time&#xf…

作者头像 李华
网站建设 2026/10/27 1:13:48

MySQL Innodb 引擎中预防 Update 操作上升为表锁

一、MySQL 如何预防 Update 上升为表锁 在 MySQL 中&#xff0c;进行任何数据的 修改 操作都会进行一定的锁操作&#xff0c;而锁的不同直接导致性能的差异。例如 MyISAM 引擎&#xff0c;更新时采用表锁&#xff0c;并发性较差。而 Innodb 引擎支持事务&#xff0c;更新时采用…

作者头像 李华
网站建设 2026/10/27 1:13:45

基于 YOLO V8 Fine-Tuning 训练自定义的目标检测模型

一、YOLO V8 YOLO V8 是由 2023 年 ultralytics 公司开源的发布&#xff0c;是结合了前几代 YOLO 的融合改进版。YOLO V8 支持全方位的视觉 AI 任务&#xff0c;包括检测、分割、姿态估计、跟踪和分类。并且在速度和准确性方面具有无与伦比的性能。能够应用在各种对速度和精度…

作者头像 李华