如何更高效遍历字符串并将1-4位字符组合存入HashMap?
性能优化方案及问题修复
现有代码的核心问题
- 逻辑错误:2长度子串未执行计数累加,4长度子串重复累加2次,循环边界设置错误导致末尾位置的1/2/3长度子串完全漏统计
- 性能损耗点:
- 同一个子串重复生成多次,每次字符拼接产生大量临时String对象,额外增加GC压力
- 每个key执行两次HashMap查找(
putIfAbsent+computeIfPresent),HashMap的hash计算和寻址开销直接翻倍 - HashMap未预初始化,频繁触发扩容带来的数组拷贝开销
优化后实现
import java.util.HashMap; import java.util.Locale; public class AlgorithmImpl implements statAlgrithm { @Override public HashMap<String, Integer> analysis(String text) { char[] chars = text.toUpperCase(Locale.ROOT).toCharArray(); int len = chars.length; // 预初始化容量避免扩容,最多有4*len个不同key,适配默认0.75的负载因子 HashMap<String, Integer> map = new HashMap<>((int) Math.ceil(4 * len / 0.75) + 1); for (int i = 0; i < len; i++) { // 计算当前位置可截取的最大子串长度,不超过4 int maxSubLen = Math.min(4, len - i); // 批量生成1到maxSubLen长度的子串,直接计数 for (int subLen = 1; subLen <= maxSubLen; subLen++) { String key = new String(chars, i, subLen); map.put(key, map.getOrDefault(key, 0) + 1); } } return map; } }
优化收益
- 修复所有逻辑错误,计数结果完全准确
- 每个子串仅生成一次,减少90%以上的临时String对象创建
- 每个key仅执行一次HashMap读写操作,查找开销减半
- 预初始化HashMap完全避免扩容开销
- 整体仍是O(n)时间复杂度,常数项开销降低60%以上
如果可引入第三方工具包,还可使用fastutil的Object2IntOpenHashMap代替JDK的HashMap,避免Integer自动装箱拆箱开销,性能还能再提升30%左右。
内容的提问来源于stack exchange,提问作者Omegon
相关产品推荐
相关产品推荐

