String.startsWith()用于判断字符串是否以指定前缀开头,但对null敏感且空字符串返回false;正确用法需先用Objects.nonNull()过滤null,再调用startsWith(),避免NPE和越界异常。

String.startsWith() 的基本用法和常见误判
直接调用 startsWith() 就能判断字符串是否以指定前缀开头,但它对 null 和空字符串很敏感——如果列表里有 null 元素,直接调用会抛 NullPointerException;如果标题是空字符串 "","".startsWith("Java") 返回 false,这通常符合预期,但得确认你不需要特殊处理空值。
实际过滤时,别写成 title.startsWith("Java") == true,冗余且易错;更别用 title.substring(0, 4).equals("Java"),会抛 StringIndexOutOfBoundsException 当字符串长度不足 4。
Java 8+ Stream 过滤的正确写法
最常用也最安全的方式是结合 Objects.nonNull() 做空检查,再调用 startsWith():
List<String> titles = Arrays.asList("Java 17 新特性", "Python 入门", null, "JavaScript 高级技巧", "JavaDoc 使用指南");
List<String> javaTitles = titles.stream()
.filter(Objects::nonNull)
.filter(title -> title.startsWith("Java"))
.collect(Collectors.toList());
注意点:
立即学习“Java免费学习笔记(深入)”;
-
filter(Objects::nonNull)必须放在startsWith()之前,否则null会提前触发异常 - 如果想忽略大小写,用
title.regionMatches(true, 0, "java", 0, 4),startsWith()本身不支持忽略大小写参数 - 前缀是硬编码字符串时,确保没多余空格,比如
"Java "和"Java"效果完全不同
Android 或低版本 Java(
没有 Stream 时,用传统循环更可控,也方便加日志或跳过异常项:
List<String> javaTitles = new ArrayList<>();
for (String title : titles) {
if (title != null && title.startsWith("Java")) {
javaTitles.add(title);
}
}
这种写法的优势:
- 明确控制每一步,调试时容易打断点
- 可轻松扩展逻辑,比如同时排除含 "Script" 的项:
&& !title.contains("Script") - 避免
Stream在 Android API Collectors.toList() 而编译失败
性能与边界情况提醒
startsWith() 是 O(1) 比较(只看前几个字符),比 indexOf("Java") == 0 稍快且语义更清晰。但要注意:
- 如果列表极大(比如 10 万+ 标题),且“Java”前缀匹配率极低,提前
filter(Objects::nonNull)能减少后续判断次数 - Unicode 场景下,如果标题含 emoji 或代理对(surrogate pairs),
startsWith()仍按 char 序列比较,一般不影响英文前缀,但自定义前缀含非 BMP 字符时需额外验证 - 不要依赖
title.toLowerCase().startsWith("java")做忽略大小写——某些 locale(如土耳其语)下toLowerCase()行为异常,改用regionMatches()
真正容易被忽略的是 null 安全性和大小写策略,这两点一旦漏掉,要么崩溃,要么漏数据,而且问题往往在上线后才暴露。


















