杰瑞科技汇

Java字符串如何判断包含另一个字符串?

Java 字符串包含全攻略:从contains()到正则表达式,一篇搞定!

在 Java 编程的世界里,字符串操作无疑是最基础也最频繁的任务之一,而“判断一个字符串中是否包含另一个字符串”,更是无数开发者在日常工作中几乎每天都会遇到的问题,无论是验证用户输入、解析数据,还是进行文本匹配,这一操作都扮演着至关重要的角色。

Java字符串如何判断包含另一个字符串?-图1
(图片来源网络,侵删)

本文将作为你的终极指南,深入浅出地探讨在 Java 中实现“字符串包含”检查的各种方法,从最基础的 contains() 方法,到更灵活强大的 indexOf(),再到处理复杂模式的正则表达式,无论你是刚入门的 Java 新手,还是寻求更优解决方案的资深开发者,相信都能在这里找到你需要的答案。


核心方法:String.contains() – 最直观的判断

当我们谈论“字符串包含”时,首先想到的几乎总是 String.contains() 方法,它就像一个“侦察兵”,能直接告诉你目标字符串中是否存在指定的子字符串。

语法与用法

contains() 方法的签名非常简洁:

public boolean contains(CharSequence s)
  • 参数 s:一个 CharSequence 对象,也就是你想要查找的子字符串,这意味着你可以直接传入 StringStringBuilderCharBuffer 等类型。
  • 返回值:一个布尔值。
    • 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 = "python";
        String subString3 = "world";
        // 检查是否包含 "Java"
        boolean containsJava = mainString.contains(subString1);
        System.out.println("主字符串是否包含 '" + subString1 + "'? " + containsJava); // 输出: true
        // 检查是否包含 "python"
        boolean containsPython = mainString.contains(subString2);
        System.out.println("主字符串是否包含 '" + subString2 + "'? " + containsPython); // 输出: false
        // 检查是否包含 "world"
        boolean containsWorld = mainString.contains(subString3);
        System.out.println("主字符串是否包含 '" + subString3 + "'? " + containsWorld); // 输出: true
        // 注意:contains() 方法是区分大小写的!
        String subString4 = "java"; // 小写 j
        boolean containsJavaLowercase = mainString.contains(subString4);
        System.out.println("主字符串是否包含 '" + subString4 + "' (区分大小写)? " + containsJavaLowercase); // 输出: false
    }
}

重要特性与注意事项

  • 区分大小写contains() 方法是大小写敏感的。"Java""java" 会被视为两个不同的字符串。
  • 空字符串 "":任何字符串(包括空字符串 )都包含空字符串,这是一个非常重要的特性,"".contains("") 的结果是 true
  • 参数为 null:如果传入的 CharSequence 参数是 nullcontains() 方法会抛出 NullPointerException,在使用前最好进行非空检查,或者使用 Java 8+ 的 Objects.requireNonNull()
// 避免 NullPointerException
String str = "some text";
if (str != null && str.contains("some")) {
    // 安全操作
}

灵活替代:String.indexOf() – 获取位置的“侦察兵”

indexOf() 方法虽然主要功能是返回子字符串首次出现的位置索引,但它同样可以用来判断“包含”关系,并且提供了更大的灵活性。

语法与用法

indexOf() 的签名如下:

public int indexOf(String str)
  • 参数 str:要查找的子字符串。
  • 返回值:子字符串首次出现的索引(从 0 开始),如果子字符串不存在,则返回 -1

我们可以通过判断返回值是否为 -1 来判断是否包含。

代码示例

public class IndexOfExample {
    public static void main(String[] args) {
        String mainString = "Learning Java is fun.";
        String subString1 = "Java";
        String subString2 = "C++";
        // 使用 indexOf() 判断包含关系
        boolean containsJava = mainString.indexOf(subString1) != -1;
        boolean containsCpp = mainString.indexOf(subString2) != -1;
        System.out.println("主字符串是否包含 '" + subString1 + "'? " + containsJava); // 输出: true
        System.out.println("主字符串是否包含 '" + subString2 + "'? " + containsCpp); // 输出: false
    }
}

何时选择 indexOf()?

虽然 contains() 更直观,但在以下场景下,indexOf() 可能是更好的选择:

  1. 需要知道位置信息:如果你不仅想知道“有没有”,还想知道“在哪儿”,indexOf() 是不二之选。
  2. 性能考量(微优化):在极少数对性能要求极致的场景下,一些早期 JVM 版本中 indexOf() 的底层实现可能比 contains() 稍快一点点,但这在现代 JVM 中几乎可以忽略不计,代码可读性永远应该优先于这种微小的性能差异

进阶之选:正则表达式 (Pattern & Matcher) – 处理复杂模式的“瑞士军刀”

当你的“包含”需求变得复杂时,

  • 不区分大小写地查找。
  • 查找满足特定格式的字符串(如邮箱、手机号)。
  • 查找包含任意数字的字符串。

这时,正则表达式就派上用场了,它虽然学习曲线稍陡,但功能强大,是处理复杂文本匹配的终极武器。

核心思想

使用正则表达式进行包含判断,通常的流程是:

  1. 编译一个正则表达式模式,得到一个 Pattern 对象。
  2. 使用 Pattern 对象和目标字符串创建一个 Matcher 对象。
  3. 调用 Matcher.find() 方法。find() 返回 true,则说明字符串中匹配了该模式。

代码示例

示例1:不区分大小写的包含
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexExample {
    public static void main(String[] args) {
        String mainString = "The Quick Brown Fox Jumps Over The Lazy Dog.";
        String regex = "fox"; // 我们要查找的模式
        // 1. 编译正则表达式,并指定不区分大小写 (CASE_INSENSITIVE)
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        // 2. 创建匹配器
        Matcher matcher = pattern.matcher(mainString);
        // 3. 调用 find() 进行查找
        boolean found = matcher.find();
        System.out.println("主字符串中是否包含 '" + regex + "' (不区分大小写)? " + found); // 输出: true
    }
}
示例2:查找包含任意数字的字符串
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexExample2 {
    public static void main(String[] args) {
        String text1 = "This is a test123 string.";
        String text2 = "This is a test string without numbers.";
        String regex = "\\d"; // \d 代表任意一个数字
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher1 = pattern.matcher(text1);
        Matcher matcher2 = pattern.matcher(text2);
        boolean containsNumber1 = matcher1.find();
        boolean containsNumber2 = matcher2.find();
        System.out.println("文本1是否包含数字? " + containsNumber1); // 输出: true
        System.out.println("文本2是否包含数字? " + containsNumber2); // 输出: false
    }
}

何时选择正则表达式?

当你的“包含”逻辑超出了简单的字符串字面量匹配时,就应该毫不犹豫地选择正则表达式,它为文本处理提供了无限可能。


性能对比与最佳实践

方法 优点 缺点 适用场景
contains() 代码最直观、可读性最高 功能单一,区分大小写 绝大多数情况下的首选,简单、快速的包含检查。
indexOf() 灵活,可获取位置索引 代码稍显冗余(需判断 != -1 需要同时知道子字符串位置时。
正则表达式 功能最强大,可处理复杂模式(不区分大小写、通配符等) 语法复杂,性能开销相对较大 处理复杂模式匹配、不区分大小写、格式验证等高级需求。

最佳实践总结

  1. 首选 contains():对于 90% 的简单包含判断场景,String.contains() 是你的最佳拍档,它的清晰和简洁是最大的优势。
  2. 拥抱正则表达式:不要害怕正则表达式,当你遇到 contains() 无法满足的需求时(如大小写不敏感、查找特定模式),立刻切换到正则表达式,这是专业能力的体现。
  3. 注意 null:始终警惕 NullPointerException,在使用 contains()indexOf() 前,确保主字符串或子字符串不为 null,或者使用 Objects.requireNonNull 进行防御性编程。
  4. 性能不是唯一标准:除非你是在一个被调用数百万次的超高频方法中,否则永远不要为了微小的性能提升而牺牲代码的可读性和可维护性。contains() 的可读性完胜。

判断 Java 字符串中是否包含另一个字符串,是编程中的基本功,我们今天系统地学习了三种主流方法:

  • String.contains():简单、直观,是日常开发中的首选
  • String.indexOf():灵活,能获取位置,是 contains() 的一个有力补充。
  • 正则表达式 (Pattern & Matcher):强大、万能,是解决复杂模式匹配问题的终极方案。

希望这篇详尽的指南能帮助你彻底掌握 Java 字符串包含的技巧,没有“最好”的方法,只有“最合适”的方法,根据你的具体需求,选择最恰当的工具,才能写出更优雅、更高效的代码。

轮到你了!在你的项目中,最常用的是哪一种方法?或者你有什么关于字符串处理的小技巧?欢迎在评论区分享你的经验和见解!

分享:
扫描分享到社交APP
上一篇
下一篇