1. 引言:为什么字符串搜索在 Java 中很重要
字符串操作是 Java 编程中最常用的操作之一。
无论是检查用户输入、解析文件内容,还是搜索特定关键字,通常都需要判断某个单词是否出现在给定的字符串中。
为满足这些需求,Java 提供了一个便利的方法 contains()。
使用该方法,你可以轻松判断一个字符串是否 部分包含 另一个字符串。
例如,如果想检查错误信息中是否包含特定关键字,contains() 只需一行代码即可实现。
在处理大量文本的场景——如 Web 应用、API 处理或日志分析——中,contains() 方法极大提升了代码的可读性和可维护性。
但也需要注意大小写敏感以及 null 的可能性等重要因素。
本文将详细阐述 Java 的 contains() 方法——从基本用法、常见错误到与其他方法的区别以及实际应用。
我们的目标是为初学者以及在实际项目中使用 Java 的开发者提供有价值的信息。
2. contains() 方法的基本语法与特性
Java 的 contains() 方法用于判断一个字符串是否 部分包含 另一个字符串。
其语法非常简洁,却在日常编程任务中极具实用性,使用频率很高。
基本语法
boolean result = targetString.contains(searchString);
该方法属于 String 类,接受一个 CharSequence(通常是 String)作为参数。
返回值为 boolean:如果目标字符串包含给定的子串则返回 true,否则返回 false。
示例代码
String message = "Java programming is fun!";
boolean hasKeyword = message.contains("programming");
System.out.println(hasKeyword); // Output: true
在上面的示例中,子串 "programming" 出现在目标字符串中,因此 contains() 返回 true。
方法特性
- 仅检查部分匹配:如果需要完全匹配,请使用
equals()。 - 大小写敏感:例如,
"Java"与"java"被视为不同(后文会详细说明)。 - 不支持正则表达式:因为它仅检查字符串是否存在,若需模式匹配请使用
matches()或Pattern类。
传入 null 时的行为
向 contains() 传入 null 会触发 NullPointerException。
例如,下面的代码会抛出异常:
String text = null;
System.out.println(text.contains("test")); // Exception occurs
同样,如果目标字符串本身为 null,也会抛出相同的异常。
因此,强烈建议在调用 contains() 之前 进行空值检查。
3. 实际使用示例与重要注意事项
Java 的 contains() 方法直观且方便,但不当使用可能导致意外的 bug 或低效代码。
本节将说明 contains() 的基本用法,并列出使用时需要留意的关键点。
3-1. 基本使用示例
下面的代码演示了检查目标字符串是否包含特定关键字的简单例子:
String sentence = "今日はJavaの勉強をしています。";
if (sentence.contains("Java")) {
System.out.println("Javaが含まれています。");
} else {
System.out.println("Javaは含まれていません。");
}
如示例所示,contains() 常与 if 语句结合使用,以实现条件分支。
3-2. 大小写敏感性
contains() 方法是 大小写敏感 的。
例如,下面的代码会返回 false:
String text = "Welcome to Java";
System.out.println(text.contains("java")); // false
在这种情况下,通常会在比较前将字符串转换为小写(或大写):
String text = "Welcome to Java";
System.out.println(text.toLowerCase().contains("java")); // true
这种方法有助于消除输入大小写差异(例如,用户输入)。
3-3. null 和空字符串的处理
使用 contains() 时,最重要的考虑之一是 null 的处理。
如果目标字符串或参数为 null,则会发生 NullPointerException。
String text = null;
System.out.println(text.contains("test")); // Runtime error
为了避免这个问题,请始终添加 null 检查:
if (text != null && text.contains("test")) {
// Safe to process
}
另请注意:
传递空字符串 ("") 总是返回 true。
String sample = "test";
System.out.println(sample.contains("")); // true
然而,这种行为在实践中很少有用,如果意外传递空字符串,可能会无意中导致 bug。
3-4. 不支持多关键字搜索
contains() 一次只能检查一个关键字。
要检查多个关键字,必须多次调用 contains() 或使用 Stream API。
String target = "エラーコード123:アクセス拒否";
if (target.contains("エラー") || target.contains("拒否")) {
System.out.println("問題のあるメッセージです。");
}
或者,对于动态关键字集:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(target::contains);
4. 经常与 contains() 比较的方法
Java 提供了几种用于比较字符串或检查特定子字符串是否存在的方法。
其中,contains() 用于“部分匹配”,但其他方法也服务于类似目的。
本节解释这些方法的特性和差异,以帮助您适当使用它们。
4-1. 与 equals() 的区别:完全匹配 vs. 部分匹配
equals() 判断两个字符串是否完全相同。
相比之下,contains() 检查部分匹配。
String a = "Java";
String b = "Java";
System.out.println(a.equals(b)); // true: Exact match
System.out.println(a.contains("av")); // true: Partial match
主要区别:
| Comparison | equals() | contains() |
|---|---|---|
| Match Type | Exact match | Partial match |
| Case Sensitivity | Sensitive | Sensitive |
| Argument Type | Object | CharSequence |
使用指南:
当值必须完全匹配时使用 equals()(例如,ID 验证)。
当部分匹配可接受时使用 contains()(例如,关键字搜索)。
4-2. 与 indexOf() 的区别:是否需要位置
indexOf() 方法也可用于检查字符串中是否存在子字符串。
区别在于,如果找到,indexOf() 返回子字符串的起始索引。
如果未找到子字符串,则返回 -1。
String text = "Hello, Java World!";
System.out.println(text.indexOf("Java")); // 7
System.out.println(text.indexOf("Python")); // -1
您也可以使用 indexOf() 来复制 contains() 的行为:
if (text.indexOf("Java") >= 0) {
System.out.println("It is contained.");
}
使用指南:
如果不需要索引,contains() 更具可读性且更可取。
4-3. 与 matches() 的区别:对正则表达式的支持
matches() 方法检查字符串是否完全匹配给定的正则表达式。
相比之下,contains() 仅检查字面子字符串匹配,不支持 regex。
String text = "abc123";
System.out.println(text.matches(".*123")); // true
System.out.println(text.contains(".*123")); // false (not regex)
如果您想要基于 regex 的部分匹配,请使用 Pattern 类:
4-4. 特性比较总结
| Method | Purpose | Return Type | Regex Support | Use Case |
|---|---|---|---|---|
contains() | Partial match | boolean | No | Keyword search |
equals() | Exact match | boolean | No | ID/password checks |
indexOf() | Get match position | int | No | Index-based processing |
matches() | Regex match | boolean | Yes | Find pattern-based strings |
5. 常见用例和示例代码
Java 的 contains() 方法简单却在实际开发场景中被广泛使用。
典型用例包括用户输入验证、日志分析和过滤操作。
本节涵盖带有相应代码的实际示例。
5-1. 用户输入验证(检测禁止词)
在表单或聊天应用中,您可能需要检测是否包含某些禁止词。
String input = "このアプリは最悪だ";
String banned = "最悪";
if (input.contains(banned)) {
System.out.println("不適切な言葉が含まれています。");
}
处理多个 NG 词:
List<String> bannedWords = Arrays.asList("最悪", "バカ", "死ね");
for (String word : bannedWords) {
if (input.contains(word)) {
System.out.println("不適切な言葉が含まれています: " + word);
break;
}
}
5-2. 日志文件分析(检测特定消息)
在分析系统或应用日志时,您可能希望仅提取包含特定关键字如 ERROR 或 WARN 的行。
List<String> logs = Arrays.asList(
"[INFO] サーバーが起動しました",
"[ERROR] データベース接続失敗",
"[WARN] メモリ使用率が高い"
);
for (String log : logs) {
if (log.contains("ERROR")) {
System.out.println("エラー発生ログ: " + log);
}
}

5-3. 列表中字符串过滤(使用 Stream API)
在处理大型数据集时,使用 Stream API 提取仅包含特定子字符串的元素:
List<String> users = Arrays.asList("tanaka@example.com", "sato@gmail.com", "yamada@yahoo.co.jp");
List<String> gmailUsers = users.stream()
.filter(email -> email.contains("@gmail.com"))
.collect(Collectors.toList());
System.out.println(gmailUsers); // [sato@gmail.com]
5-4. 解析 HTTP 请求头或 URL
在 Web 开发中,路由或设备特定处理可能需要检查 User-Agent 或 URL 中的子字符串。
String userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)";
if (userAgent.contains("iPhone")) {
System.out.println("スマートフォンからのアクセスです。");
}
5-5. 检查文件路径或扩展名
使用其路径确定文件类型:
String filePath = "/usr/local/data/sample.csv";
if (filePath.contains(".csv")) {
System.out.println("CSVファイルです。");
}
注意:
对于文件扩展名检查,endsWith(".csv") 通常更准确。
实际考虑事项
- 当需要准确性时,应用规范化(例如
toLowerCase()、trim())。 - 对于大规模数据,考虑 Stream API 或正则表达式。
- 记住
contains()是部分匹配——与其他条件结合以获得更安全的逻辑。
6. 性能考虑
虽然 contains() 方法提供了出色的可读性和简单性,但在处理大型数据集或运行重复操作时,您必须考虑其 性能影响。
本节解释 contains() 的处理成本以及提高效率的替代方法。
6-1. contains() 的内部行为和时间复杂度
contains() 方法从开头 顺序搜索 目标字符串以定位子字符串。
内部,它依赖于 indexOf() 方法,其最坏情况时间复杂度为:
O(n * m)
– n = 目标字符串的长度
– m = 搜索字符串的长度
繁重处理的示例:
for (String line : hugeTextList) {
if (line.contains("error")) {
// processing
}
}
这在大型循环中重复时会显著影响性能。
6-2. 在频繁搜索期间提高性能的技术
在大型数据集中重复使用 contains() 时,以下技术可以提高处理速度:
• 提前将所有字符串转换为小写
而不是在每次比较时调用 toLowerCase(),提前规范化字符串:
List<String> normalizedList = originalList.stream()
.map(String::toLowerCase)
.collect(Collectors.toList());
• 使用带有 parallel() 的 Stream API 进行并行处理
利用 CPU 核心来加速搜索:
List<String> result = hugeTextList.parallelStream()
.filter(line -> line.contains("keyword"))
.collect(Collectors.toList());
• 对于复杂搜索模式使用正则表达式
如果条件复杂且可以用一个正则表达式表示,Pattern 可能性能更好:
Pattern pattern = Pattern.compile("error|fail|fatal");
for (String log : logs) {
if (pattern.matcher(log).find()) {
// matched
}
}
6-3. 内存效率和可重用性考虑
频繁转换字符串的操作——如 toLowerCase() 或 substring()——可能会生成许多不必要的字符串对象,影响内存使用。
这对于长运行的应用或服务器端处理尤为重要。
关键点:
- 避免创建不必要的字符串实例。
- 对于大型数据集,考虑缓冲或分块处理。
- 缓存重复的
contains()结果在某些情况下可能提高性能。
7. 与其他编程语言的比较
Java 的 contains() 方法提供了简单、可靠的子字符串匹配,但其他语言也提供了类似的功能,各有特色。
本节比较 Python、JavaScript 和 C# 中的子字符串检查,以突出差异和相似性。
7-1. Python:使用 in 操作符进行简单部分匹配
在 Python 中,你可以使用 in 操作符检查子字符串包含:
text = "Hello, Python!"
if "Python" in text:
print("含まれています")
这种语法极其易读——几乎像自然语言一样——并且学习成本最低。
差异和注意事项:
in是语言操作符,而不是方法。- Python 的字符串比较也是区分大小写的。
None会引发异常;需要进行 null 检查。
7-2. JavaScript:使用 includes() 进行部分匹配
在 JavaScript(ES6+)中,你可以使用 includes() 方法:
const text = "JavaScript is fun";
console.log(text.includes("fun")); // true
此方法与 Java 的 contains() 非常相似,便于在脑海中迁移。
差异和注意事项:
- 传递
undefined不会抛出异常;它只是返回false。 includes()也适用于数组,提高了其多功能性。
7-3. C#:类似于 Java 的 Contains()
C# 也提供了行为类似于 Java 的 Contains() 方法:
string text = "Welcome to C#";
bool result = text.Contains("C#");
差异和注意事项:
- C# 的
Contains()默认区分大小写,但你可以使用StringComparison.OrdinalIgnoreCase忽略大小写。 - 传递 null 会触发
ArgumentNullException。
7-4. 跨语言比较表
| Language | Example Syntax | Case Sensitivity | Notes |
|---|---|---|---|
| Java | "abc".contains("a") | Sensitive | Throws exception on null |
| Python | "a" in "abc" | Sensitive | Most intuitive syntax |
| JavaScript | "abc".includes("a") | Sensitive | Also works for arrays |
| C# | "abc".Contains("a") | Sensitive (configurable) | Comparison mode can be chosen |
总结:为你的用例选择合适的语法
尽管子字符串检查是跨语言的常见需求,但每种语言都提供了自己的方法或语法。
Java 的 contains() 提供了稳定性和清晰度,使其非常适合企业系统和可维护的应用。
像 Python 和 JavaScript 这样的语言提供了更简单、更简洁的语法,这对于轻量级脚本或快速原型开发非常理想。
通过理解共同概念以及每种语言的具体特性,你将能够跨各种语言编写更安全、更高效的代码。
8. 常见问题解答 (FAQ)
以下是关于 Java 的 contains() 方法的常见问题——帮助你理解棘手点并避免常见陷阱。
Q1. contains() 是否区分大小写?
是的,它是区分大小写的。
例如,"Java".contains("java") 返回 false。
解决方案:
String input = "Welcome to Java";
boolean result = input.toLowerCase().contains("java");
Q2. 如何使用正则表达式检查部分匹配?
contains() 不支持正则表达式。
使用 matches() 或 Pattern 类代替。
示例(检查数字模式):
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "注文番号: A123456";
Pattern pattern = Pattern.compile("A\\d+");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("パターンに一致しました。");
}
Q3. 如果对 null 调用 contains() 会怎样?
会抛出 NullPointerException。
String target = null;
System.out.println(target.contains("test")); // Error
解决方案:
if (target != null && target.contains("test")) {
System.out.println("含まれています。");
}
Q4. 如果向 contains() 传入空字符串(””)会怎样?
它总是返回 true。
String text = "Java";
System.out.println(text.contains("")); // true
虽然这是官方规范的一部分,但此行为很少有用,如果不打算使用空字符串,可能会导致意外的错误。
Q5. contains() 能一次搜索多个关键字吗?
不能。每次调用只能检查一个关键字。
String text = "本日はシステムエラーが発生しました";
if (text.contains("エラー") || text.contains("障害") || text.contains("失敗")) {
System.out.println("問題が検出されました。");
}
动态方法:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(text::contains);
Q6. 何时应该使用 contains() 而不是 indexOf()?
contains() 返回布尔值,而 indexOf() 返回数值索引。
- 当你只想知道子串是否存在时使用
contains()。 - 当你还需要知道子串位置时使用
indexOf()。String text = "Error: Disk full"; if (text.contains("Error")) { int pos = text.indexOf("Error"); System.out.println("Position: " + pos); }
9. 结论
Java 的 contains() 方法是一个强大且便利的工具,用于判断特定子串是否 包含在字符串中。
它在用户输入验证、日志分析和数据过滤等各种场景中被广泛使用。
本文涵盖了以下内容:
- 基本语法和返回值
- 大小写敏感性及其处理方法
- 处理 null 和空字符串
- 与其他字符串比较方法的区别
- 实际用例:验证、日志搜索、Stream 处理
- 性能考虑和优化技术
- 与 Python、JavaScript 和 C# 的比较
- 常见问题及排错技巧
虽然 contains() 直观且多功能,但在涉及 大数据集、频繁调用 或 复杂搜索条件 的情况下应慎重使用。
通过结合规范化、并行处理、正则表达式和缓存策略,你可以兼顾性能和可读性。
由于 contains() 是 Java 字符串处理的基础,我们希望本文能帮助你在开发项目中更安全、更高效地使用它。

