最高效方式是遍历char数组计数,时间复杂度o(n)、空间复杂度o(1);超长字符串且目标字符极少时可用indexof跳跃查找;避免流式处理、正则、split等高开销方法。

Java 中统计字符串中某个字符出现的次数,最高效的方式是遍历一次字符串,用一个计数器累加匹配次数。避免创建中间对象(如正则匹配、分割数组、流式处理等),能显著提升性能,尤其在高频调用或长字符串场景下。
直接遍历 char 数组(推荐)
将字符串转为 char[] 后遍历,比反复调用 String.charAt(i) 略快(JVM 优化后差距变小,但语义清晰、稳定高效)。
- 时间复杂度:O(n),仅一次扫描
- 空间复杂度:O(1),无额外集合或字符串生成
- 适合所有 Java 版本,无兼容性问题
示例代码:
public static int countChar(String str, char target) {
if (str == null) return 0;
int count = 0;
for (char c : str.toCharArray()) {
if (c == target) count++;
}
return count;
}
使用 String.indexOf 循环查找(适合超长字符串 + 少量匹配)
当目标字符在字符串中出现极少(比如找 '
当目标字符在字符串中出现极少(比如找 '\0' 或特殊分隔符),用 indexOf 跳跃式查找可减少无效比较,实际性能可能略优。
indexOf 跳跃式查找可减少无效比较,实际性能可能略优。- 避免创建 char 数组(节省临时内存)
- 每次从上一位置+1开始搜索,天然跳过不匹配区域
- 注意:对均匀分布的字符(如统计 'a' 在英文文本中),通常不如直接遍历
示例代码:
public static int countCharByIndex(String str, char target) {
if (str == null) return 0;
int count = 0, index = -1;
while ((index = str.indexOf(target, index + 1)) != -1) {
count++;
}
return count;
}
慎用的“简洁写法”及其代价
以下方式虽代码短,但不推荐用于性能敏感场景:
-
str.chars().filter(ch -> ch == target).count():创建 IntStream,装箱开销大,GC 压力高 -
str.replaceAll("[^"+target+"]", "").length():正则编译 + 全字符串重建,O(n) 空间 + 隐式循环多次 -
str.split(String.valueOf(target), -1).length - 1:生成字符串数组,内存占用高,且对空字符等边界处理易出错
补充:区分大小写与 Unicode 安全(进阶注意)
上述方法默认按 char 比较,对基本多文种平面(BMP)字符完全正确;但若字符串含增补字符(如某些 emoji),char 可能拆分代理对,导致漏统计。
- 如需完整 Unicode 支持,改用
String.codePoints()流式遍历(Java 8+) - 示例:
str.codePoints().filter(cp -> cp == targetCodePoint).count(),其中targetCodePoint是字符的 Unicode 码点(如Character.codePointAt("?", 0)) - 普通英文、数字、ASCII 符号无需升级,日常开发中绝大多数场景用
char遍历已足够
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











