在 Java 中,判断一个字符串(主字符串)是否包含另一个字符串(子字符串)有几种常见的方法,下面我将为你详细介绍,并提供代码示例和优缺点分析。
使用 String.contains() 方法(最常用)
这是最直接、最常用的方法,它专门用于检查字符串中是否包含指定的字符序列。
语法
public boolean contains(CharSequence sequence)
sequence:要搜索的字符序列(通常是另一个字符串)。- 返回值:如果包含,返回
true;否则返回false。 - 注意:此方法区分大小写。
示例代码
public class ContainsExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming!";
String subString1 = "Java";
String subString2 = "java"; // 注意大小写
String subString3 = "Python";
String subString4 = ""; // 空字符串
// 测试包含关系
System.out.println(mainString.contains(subString1)); // 输出: true
System.out.println(mainString.contains(subString2)); // 输出: false (因为大小写不匹配)
System.out.println(mainString.contains(subString3)); // 输出: false
System.out.println(mainString.contains(subString4)); // 输出: true (空字符串总是被包含)
}
}
优点
- 简单直观:方法名
contains语义非常清晰。 - 性能良好:对于大多数场景,性能已经足够。
缺点
- 区分大小写:如果需要进行不区分大小写的判断,需要额外处理。
- 不支持正则表达式:如果需要进行更复杂的模式匹配,此方法不适用。
使用 String.indexOf() 方法
indexOf() 方法返回子字符串在主字符串中首次出现的索引,如果找不到,它会返回 -1,我们可以通过检查返回值是否为 -1 来判断是否包含。
语法
public int indexOf(String str)
str:要搜索的子字符串。- 返回值:如果找到,返回子字符串的起始索引;如果未找到,返回
-1。
示例代码
public class IndexOfExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming!";
String subString1 = "Java";
String subString2 = "python";
// indexOf 方法判断
boolean isContains1 = mainString.indexOf(subString1) != -1;
boolean isContains2 = mainString.indexOf(subString2) != -1;
System.out.println(mainString + " 包含 " + subString1 + " 吗? " + isContains1); // 输出: true
System.out.println(mainString + " 包含 " + subString2 + " 吗? " + isContains2); // 输出: false
}
}
优点
- 兼容性好:这是一个非常基础的方法,在所有 Java 版本中都可用。
- 功能更多:除了判断是否存在,还可以获取子字符串的位置,这在某些场景下很有用。
缺点
- 代码稍显冗长:需要写
!= -1的判断,不如contains()方法简洁。 - 同样区分大小写。
使用 java.util.regex.Pattern 和 String.matches()(用于正则表达式)
如果你的判断逻辑不仅仅是简单的字符串匹配,而是需要更复杂的模式(以 "Java" 开头,或包含数字等),那么使用正则表达式是最佳选择。
String.matches() 方法可以判断整个字符串是否完全匹配给定的正则表达式,如果你想判断字符串是否包含某个模式,应该使用 Pattern.matcher().find()。
示例代码(判断是否包含)
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexContainsExample {
public static void main(String[] args) {
String mainString = "Order ID: 12345, Status: Shipped";
// 检查是否包含一个或多个数字
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(mainString);
boolean containsDigits = matcher.find(); // find() 查找任意匹配的子序列
System.out.println("字符串是否包含数字? " + containsDigits); // 输出: true
// 检查是否包含 "Order ID:"
boolean containsOrderId = mainString.matches(".*Order ID:.*");
// 或者更严谨的写法:
boolean containsOrderIdStrict = Pattern.compile("Order ID:").matcher(mainString).find();
System.out.println("字符串是否包含 'Order ID:'? " + containsOrderId); // 输出: true
}
}
matches():整个字符串必须完全匹配正则表达式才返回true。".*Order ID:.*"的意思是:任意字符()开头,然后是 "Order ID:",再然后是任意字符结尾。Pattern.matcher().find():查找字符串中是否存在匹配正则表达式的子序列,更符合“包含”的含义。
优点
- 功能强大:可以处理极其复杂的文本匹配规则。
- 非常灵活:可以定义字符类、量词、边界等。
缺点
- 性能较低:对于简单的字符串包含判断,正则表达式的解析和匹配开销较大。
- 语法复杂:需要学习正则表达式语法,对于简单场景是小题大做。
不区分大小写的判断
如果需要进行不区分大小写的判断,可以先将主字符串和子字符串都转换为统一的大小写(都转为小写),然后再进行比较。
示例代码
public class CaseInsensitiveExample {
public static void main(String[] args) {
String mainString = "Hello, welcome to the world of Java programming!";
String subString = "java";
// 方法1:使用 contains() + toLowerCase()
boolean isContainsIgnoreCase1 = mainString.toLowerCase().contains(subString.toLowerCase());
System.out.println("使用 contains() + toLowerCase() 判断: " + isContainsIgnoreCase1); // 输出: true
// 方法2:使用 indexOf() + toLowerCase()
boolean isContainsIgnoreCase2 = mainString.toLowerCase().indexOf(subString.toLowerCase()) != -1;
System.out.println("使用 indexOf() + toLowerCase() 判断: " + isContainsIgnoreCase2); // 输出: true
// 方法3:使用正则表达式 (更灵活,可以处理特定语言的 locale)
boolean isContainsIgnoreCase3 = Pattern.compile(Pattern.quote(subString), Pattern.CASE_INSENSITIVE)
.matcher(mainString)
.find();
System.out.println("使用正则表达式判断: " + isContainsIgnoreCase3); // 输出: true
}
}
注意:Pattern.quote(subString) 是一个好习惯,它会将 subString 中的特殊正则字符(如 、 等)进行转义,确保你匹配的是字面字符串,而不是正则表达式元字符。
总结与最佳实践
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
String.contains() |
最简单、最直观、性能好 | 区分大小写 | 绝大多数情况下的首选。 |
String.indexOf() |
兼容性好,可获取位置 | 代码稍长 | 当你不仅想知道“是否包含”,还想知道“在哪里”时。 |
Pattern.matcher().find() |
功能最强大,支持正则 | 性能较低,语法复杂 | 需要复杂模式匹配时,如查找特定格式(邮箱、手机号)。 |
| 大小写不敏感比较 | 灵活 | 需要额外转换 | 需要忽略大小写的场景。 |
最佳实践建议:
-
对于简单的包含判断:直接使用
String.contains(),这是最符合 Java 编码习惯的方式。if (myString.contains("target")) { // ... } -
对于不区分大小写的判断:使用
toLowerCase()或toUpperCase()进行预处理。if (myString.toLowerCase().contains("target".toLowerCase())) { // ... } -
对于需要获取子字符串位置的场景:使用
String.indexOf()。int index = myString.indexOf("target"); if (index != -1) { // ... 找到了,起始位置是 index } -
对于复杂的模式匹配(如验证格式):使用
java.util.regex包。// 检查是否包含至少一个数字 if (Pattern.compile("\\d").matcher(myString).find()) { // ... }
