导读:本期聚焦于小伙伴创作的《Java中如何判断字符串是否包含子串?contains与indexOf底层对比》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Java中如何判断字符串是否包含子串?contains与indexOf底层对比》有用,将其分享出去将是对创作者最好的鼓励。

在Java编程中,判断一个字符串是否包含指定子串是日常开发中非常常见的需求,Java的String类提供了contains和indexOf两个方法来实现这类判断,很多开发者对两者的区别和底层实现并不清晰,本文将详细展开分析。

Java中如何判断字符串是否包含子串?contains与indexOf底层对比

两个方法的基本用法

首先我们来看两个方法的基础使用方式,两者的调用形式都比较简单,先给出基础的代码示例。

public class StringContainsDemo {
    public static void main(String[] args) {
        String mainStr = "hello world java";
        String subStr = "world";
        
        // 使用contains方法判断
        boolean containsResult = mainStr.contains(subStr);
        System.out.println("contains判断结果:" + containsResult);
        
        // 使用indexOf方法判断
        int indexOfResult = mainStr.indexOf(subStr);
        boolean indexOfCheck = indexOfResult != -1;
        System.out.println("indexOf判断结果:" + indexOfCheck);
    }
}

从上面的代码可以看到,contains方法直接返回布尔值,而indexOf方法返回子串在主串中首次出现的索引位置,当返回-1时表示不存在子串,因此需要通过判断返回值是否不等于-1来得到是否包含的布尔结果。

底层实现源码对比

contains方法的源码

我们先查看String类中contains方法的实现,源码如下:

public boolean contains(CharSequence s) {
    // 调用indexOf方法,判断返回值是否大于等于0
    return indexOf(s.toString()) >= 0;
}

可以看到contains方法本身没有额外的复杂逻辑,它本质上是直接调用了indexOf方法,然后判断indexOf的返回值是否大于等于0,如果大于等于0就返回true,否则返回false。

indexOf方法的源码

接下来看indexOf方法的实现,String类中有多个重载的indexOf方法,最常用的是接收String参数的版本,其核心逻辑如下:

public int indexOf(String str) {
    return indexOf(str, 0);
}

public int indexOf(String str, int fromIndex) {
    return indexOf(value, 0, value.length,
                   str.value, 0, str.value.length, fromIndex);
}

最终会调用一个静态的indexOf方法,这个方法是实现子串查找的核心,底层采用的是经典的朴素字符串匹配算法,源码简化后逻辑如下:

static int indexOf(char[] source, int sourceOffset, int sourceCount,
                   char[] target, int targetOffset, int targetCount,
                   int fromIndex) {
    if (fromIndex >= sourceCount) {
        return (targetCount == 0 ? sourceCount : -1);
    }
    if (fromIndex < 0) {
        fromIndex = 0;
    }
    if (targetCount == 0) {
        return fromIndex;
    }
    char first = target[targetOffset];
    int max = sourceOffset + (sourceCount - targetCount);
    for (int i = sourceOffset + fromIndex; i <= max; i++) {
        // 先找到第一个匹配的字符
        if (source[i] != first) {
            while (++i <= max && source[i] != first);
        }
        // 找到第一个匹配字符后,继续匹配后续字符
        if (i <= max) {
            int j = i + 1;
            int end = j + targetCount - 1;
            for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++);
            if (j == end) {
                // 匹配成功,返回索引
                return i - sourceOffset;
            }
        }
    }
    return -1;
}

从源码可以看出,indexOf的底层实现是从主串的指定位置开始,逐个字符匹配子串,时间复杂度为O(n*m),其中n是主串长度,m是子串长度。

两者的核心差异

对比维度contains方法indexOf方法
返回值类型布尔值,直接返回是否包含子串整型,返回子串首次出现的索引,不存在返回-1
功能范围仅能判断是否存在子串不仅能判断是否存在,还能获取子串的位置,也支持从指定索引开始查找
底层实现直接调用indexOf方法,无额外逻辑实现朴素字符串匹配算法,是子串查找的核心实现
性能表现和indexOf判断是否存在时的性能几乎一致,仅多了一层方法调用单独使用时如果只需要判断是否存在,会多一次返回值比较的开销(可忽略)

实际开发中的选择建议

根据两者的特性,我们可以按照以下场景选择:

  • 如果只需要判断字符串是否包含子串,不需要知道子串的位置,优先使用contains方法,代码可读性更高,语义更明确。
  • 如果需要获取子串在主串中的位置,或者需要从指定索引开始查找子串,只能使用indexOf方法。
  • 如果既需要判断是否存在,又需要后续使用子串的位置,那么直接使用indexOf方法保存返回值,避免重复调用查找逻辑。

需要注意,两者的底层匹配算法都是朴素匹配,在处理超长字符串且对性能要求极高的场景下,可能需要考虑使用更高效的字符串匹配算法,比如KMP算法,但普通业务场景下两者的性能完全足够使用。

JavacontainsindexOf字符串包含底层原理修改时间:2026-06-10 23:42:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。