indexOf()
是 Java String
类中最常用、最核心的查找方法之一,用于定位字符或子串在字符串中的位置。
方法定义
String
类提供了四个重载的 indexOf()
方法:
// 1. 查找指定字符第一次出现的索引
public int indexOf(int ch)
// 2. 从指定索引开始查找字符第一次出现的索引
public int indexOf(int ch, int fromIndex)
// 3. 查找指定子字符串第一次出现的索引
public int indexOf(String str)
// 4. 从指定索引开始查找子字符串第一次出现的索引
public int indexOf(String str, int fromIndex)
返回值:
- 找到时返回首次出现的索引位置(从 0 开始)。
- 未找到时返回
-1
。
参数说明:
ch
:要查找的字符(int
类型,兼容char
)。str
:要查找的子字符串。fromIndex
:开始搜索的起始索引(包含该位置)。若为负数,按 0 处理。
功能说明
indexOf()
的核心功能是在字符串中搜索目标字符或子串,并返回其第一次出现的位置。
- 搜索方向: 总是从左到右(从前向后)扫描。
- 区分大小写: 搜索是区分大小写的。
- 返回
-1
: 表示未找到匹配项,这是判断“不存在”的关键依据。 - 起始索引:
fromIndex
参数允许跳过字符串前部,从指定位置开始搜索,常用于查找第二次及以后的出现位置。
示例代码
基础用法
public class IndexOfExample {
public static void main(String[] args) {
String text = "Hello, Java Programming!";
// 查找字符
System.out.println(text.indexOf('a')); // 输出: 7 (第一个 'a')
System.out.println(text.indexOf('z')); // 输出: -1 (未找到)
// 从指定位置开始查找字符
System.out.println(text.indexOf('a', 8)); // 输出: 14 (第二个 'a')
// 查找子字符串
System.out.println(text.indexOf("Java")); // 输出: 7
System.out.println(text.indexOf("java")); // 输出: -1 (区分大小写)
// 从指定位置开始查找子串
System.out.println(text.indexOf("gram", 15)); // 输出: 20
}
}
查找所有出现位置
public static void findAllOccurrences(String text, String target) {
int index = text.indexOf(target);
while (index != -1) {
System.out.println("Found '" + target + "' at index: " + index);
index = text.indexOf(target, index + 1); // 从下一个位置继续查找
}
}
// 调用
findAllOccurrences("banana", "ana");
// 输出:
// Found 'ana' at index: 1
// Found 'ana' at index: 3
判断子串是否存在(推荐方式)
String sentence = "I love Java and JavaScript";
boolean containsJava = sentence.indexOf("Java") != -1;
System.out.println(containsJava); // true
使用技巧
快速判断存在性
使用indexOf(str) != -1
是判断子串是否存在的最高效方式之一,比contains()
在某些 JDK 版本中略快(但contains()
更语义清晰)。查找第 N 次出现
结合循环和fromIndex
参数,轻松实现查找第 2、第 3 次出现的位置。定位分隔符位置
常用于解析字符串,如查找第一个逗号、等号、冒号等。String config = "name=John,age=30"; int eqIndex = config.indexOf('='); String value = config.substring(eqIndex + 1, config.indexOf(',', eqIndex));
与
lastIndexOf()
配合
lastIndexOf()
从后往前找,两者结合可处理复杂字符串提取。String path = "/home/user/docs/file.txt"; int lastSlash = path.lastIndexOf('/'); String fileName = path.substring(lastSlash + 1); // "file.txt"
链式调用定位边界
在解析协议或格式化文本时非常有用。String html = "<title>My Page</title>"; int start = html.indexOf("<title>") + 7; int end = html.indexOf("</title>"); String title = html.substring(start, end);
常见错误
忽略返回值
-1
String str = "Hello"; int pos = str.indexOf("World"); // 错误:直接使用 pos 而不检查 char nextChar = str.charAt(pos + 1); // 抛出 StringIndexOutOfBoundsException
纠正:
if (pos != -1 && pos + 1 < str.length()) { char nextChar = str.charAt(pos + 1); }
混淆大小写
"Java".indexOf("java") // 返回 -1,因为区分大小写
纠正: 使用
toLowerCase()
预处理或indexOf()
无法解决,需用正则或Pattern
。fromIndex
越界或负数"abc".indexOf('a', 10); // 不报错,返回 -1 "abc".indexOf('a', -5); // 不报错,按 0 处理,返回 0
虽然不会抛异常,但逻辑可能出错。
空字符串查找
"abc".indexOf("") // 返回 0,因为空串在任何位置都“匹配” "abc".indexOf("", 2) // 返回 2
注意事项
性能为 O(n)
最坏情况下需要扫描整个字符串,时间复杂度为 O(n)。对超长字符串频繁调用需谨慎。区分大小写
如需忽略大小写,应先统一转换:String lowerText = text.toLowerCase(); int pos = lowerText.indexOf(target.toLowerCase());
空指针安全
调用对象为null
时会抛出NullPointerException
。String s = null; s.indexOf("a"); // NullPointerException
空字符串行为
查找空字符串""
总是返回fromIndex
(或 0),需根据业务判断是否合理。字符编码
对 Unicode 字符(如 emoji)查找时,int ch
可正确处理代理对(通过码点),但String
参数需注意编码一致性。
最佳实践与性能优化
优先使用
indexOf()
判断存在性
比contains()
略高效(JDK 8-17 中contains()
内部调用indexOf()
,语义更清晰)。避免在循环中重复调用
如果需多次查找同一模式,考虑使用Pattern
和Matcher
(尤其复杂模式)或缓存结果。结合
StringBuilder
使用时注意
StringBuilder
也提供indexOf()
,适用于可变字符串场景。使用
CharSequence
接口提高兼容性
方法参数可声明为CharSequence
,兼容String
、StringBuilder
等。性能敏感场景考虑 Boyer-Moore 等算法
对固定模式的高频查找,可使用第三方库(如 Apache Commons Lang 的StringUtils.indexOf()
优化版本)。替代方案对比 | 场景 | 推荐方法 | |---|---| | 简单存在判断 |
indexOf() != -1
或contains()
| | 忽略大小写 |toLowerCase().indexOf()
| | 正则匹配 |Pattern.matcher().find()
| | 多次查找同一串 | 缓存fromIndex
循环 | | 从后往前找 |lastIndexOf()
|
总结
String.indexOf()
是 Java 字符串处理的基石方法,掌握其核心要点可大幅提升开发效率与代码健壮性。
✅ 核心要点回顾:
- 返回首次匹配的索引,未找到返回
-1
。 - 区分大小写,支持从指定位置开始搜索。
- 时间复杂度 O(n),适用于大多数查找场景。
- 必须检查
-1
防止越界错误。 - 与
lastIndexOf()
、substring()
配合可实现强大解析功能。
🚀 实践建议:
- 简单查找用
indexOf()
,语义清晰用contains()
。 - 查找多次出现时,用
index = indexOf(target, index + 1)
循环。 - 避免忽略
-1
导致运行时异常。 - 性能瓶颈时考虑正则或专用算法。
indexOf()
虽简单,却是字符串处理的“瑞士军刀”。熟练掌握其用法,是每个 Java 开发者的必备技能。