安徽省网站建设_网站建设公司_MySQL_seo优化
2025/12/22 13:42:58 网站建设 项目流程

Java 字符串查找

一、方法 1:indexOf ()/lastIndexOf ()(基础位置查找)

indexOf() 是 Java 字符串最基础的查找方法,用于定位字符 / 子串首次出现的索引lastIndexOf() 则定位最后一次出现的索引,两者是处理简单查找需求的首选。

核心语法

// 查找字符首次出现的索引
int indexOf(int ch);
// 从指定位置开始查找字符
int indexOf(int ch, int fromIndex);
// 查找子串首次出现的索引
int indexOf(String str);
// 从指定位置开始查找子串
int indexOf(String str, int fromIndex);// lastIndexOf() 语法与indexOf()一致,仅查找方向相反(从末尾往前)
 

完整代码示例 

public class StringSearchDemo {public static void main(String[] args) {String original = "Java is a programming language, Java is easy to learn";// 空值校验(实际开发必备)if (original == null) {System.out.println("字符串不能为空");return;}// 1. 查找字符首次出现的索引(字符'a'的ASCII码是97,也可直接传'a')int charFirstIndex = original.indexOf('a');System.out.println("字符'a'首次出现的索引:" + charFirstIndex); // 输出:1// 2. 查找子串首次出现的索引int strFirstIndex = original.indexOf("Java");System.out.println("子串'Java'首次出现的索引:" + strFirstIndex); // 输出:0// 3. 从指定位置(索引10)开始查找子串int strFromIndex = original.indexOf("Java", 10);System.out.println("从索引10开始查找'Java'的索引:" + strFromIndex); // 输出:32// 4. 查找子串最后一次出现的索引int strLastIndex = original.lastIndexOf("Java");System.out.println("子串'Java'最后一次出现的索引:" + strLastIndex); // 输出:32// 5. 查找不存在的子串(返回-1,核心判断依据)int notExistIndex = original.indexOf("Python");System.out.println("不存在的子串返回值:" + notExistIndex); // 输出:-1}
}
 

关键说明

  • 返回值规则:找到则返回索引(从 0 开始),未找到返回-1(这是判断是否存在的核心依据);
  • 性能特点:时间复杂度O(n)(n 为字符串长度),底层基于字符数组遍历,效率极高;
  • 适用场景:简单的字符 / 子串位置查找(如判断关键词是否存在、提取指定位置前的文本)。

二、方法 2:contains ()(存在性判断)

若仅需判断子串是否存在,无需获取具体索引,优先使用contains(),代码更简洁、语义更清晰。

核心语法

boolean contains(CharSequence s);
 

完整代码示例

public class StringSearchDemo {public static void main(String[] args) {String original = "Hello Java, Hello World";// 判断子串是否存在boolean hasJava = original.contains("Java");boolean hasPython = original.contains("Python");System.out.println("是否包含'Java':" + hasJava); // 输出:trueSystem.out.println("是否包含'Python':" + hasPython); // 输出:false}
}
 

关键说明

  • 底层逻辑contains() 本质是调用 indexOf(s) != -1,性能与indexOf()一致;
  • 适用场景:仅需判断 “有 / 无” 的场景(如表单关键词过滤、文本内容校验);
  • 注意点:参数是CharSequence类型,可直接传入 String、StringBuilder 等,无需类型转换。

三、方法 3:matches ()(正则表达式匹配)

当查找需求涉及复杂规则(如手机号、邮箱、模糊匹配),需使用matches()结合正则表达式,实现灵活的模式查找。

核心语法 

boolean matches(String regex);
 

完整代码示例 

public class StringSearchDemo {public static void main(String[] args) {// 1. 匹配邮箱格式String email = "test@example.com";String emailRegex = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";boolean isEmail = email.matches(emailRegex);System.out.println("是否为合法邮箱:" + isEmail); // 输出:true// 2. 匹配手机号(11位,以1开头)String phone = "13812345678";String phoneRegex = "^1[3-9]\\d{9}$";boolean isPhone = phone.matches(phoneRegex);System.out.println("是否为合法手机号:" + isPhone); // 输出:true// 3. 模糊匹配(包含任意数字)String text = "Java8 is better than Java7";String numRegex = ".*\\d+.*"; // .*表示任意字符,\\d+表示至少一个数字boolean hasNum = text.matches(numRegex);System.out.println("是否包含数字:" + hasNum); // 输出:true}
}
 

关键说明

  • 底层逻辑:基于正则表达式引擎匹配,功能强大但性能低于indexOf()/contains()
  • 适用场景:复杂规则匹配(如格式校验、模糊查找、特殊字符过滤);
  • 注意点matches() 会匹配整个字符串(而非子串),若需匹配子串,需在正则前后加.*

四、方法 4:Pattern + Matcher(高效正则查找)

matches() 每次调用都会重新编译正则表达式,若需高频次匹配同一规则(如批量校验 10 万条手机号),需使用Pattern预编译正则,结合Matcher实现高效查找。

完整代码示例 

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class StringSearchDemo {public static void main(String[] args) {// 预编译正则表达式(仅编译一次,复用多次)Pattern phonePattern = Pattern.compile("^1[3-9]\\d{9}$");// 批量校验手机号String[] phones = {"13812345678", "12345678901", "19987654321"};for (String phone : phones) {Matcher matcher = phonePattern.matcher(phone);boolean isPhone = matcher.matches();System.out.println(phone + " 是否为合法手机号:" + isPhone);}// 查找字符串中所有数字子串String text = "Java8 发布于2014年,Java17 发布于2021年";Pattern numPattern = Pattern.compile("\\d+"); // 匹配数字子串Matcher numMatcher = numPattern.matcher(text);System.out.println("\n提取的数字子串:");while (numMatcher.find()) { // 遍历所有匹配的子串String num = numMatcher.group(); // 获取匹配的内容int start = numMatcher.start(); // 获取匹配的起始索引int end = numMatcher.end(); // 获取匹配的结束索引System.out.println("内容:" + num + ",起始索引:" + start + ",结束索引:" + end);}}
}
 

输出结果

13812345678 是否为合法手机号:true
12345678901 是否为合法手机号:false
19987654321 是否为合法手机号:true提取的数字子串:
内容:8,起始索引:4,结束索引:5
内容:2014,起始索引:9,结束索引:13
内容:17,起始索引:18,结束索引:20
内容:2021,起始索引:24,结束索引:28
 

关键说明

  • 核心优势Pattern预编译后可复用,避免重复编译正则的性能损耗,高频场景下效率提升 10 倍以上;
  • 核心方法
    • matcher.find():查找下一个匹配的子串;
    • matcher.group():获取当前匹配的内容;
    • matcher.start()/end():获取匹配内容的起止索引;
  • 适用场景:批量数据校验、提取字符串中所有符合规则的子串。

五、方法 5:String.indexOf () 循环查找(批量子串查找)

若需查找字符串中所有目标子串的位置(如统计关键词出现次数),可通过indexOf()循环实现,相比正则更高效。

完整代码示例 

public class StringSearchDemo {public static void main(String[] args) {String original = "Java is Java, Java is everywhere";String target = "Java";int count = 0; // 统计出现次数int index = 0; // 起始查找位置// 循环查找所有目标子串while ((index = original.indexOf(target, index)) != -1) {count++;System.out.println("找到'" + target + "',索引:" + index);index += target.length(); // 移动查找位置,避免重复匹配}System.out.println("'" + target + "' 总共出现:" + count + " 次");}
}
 

输出结果

找到'Java',索引:0
找到'Java',索引:8
找到'Java',索引:14
'Java' 总共出现:3 次
 

关键说明

  • 核心逻辑:每次找到子串后,将查找起始位置移至当前索引 + 子串长度,避免重复匹配(如 “JavaJava” 中只匹配两次);
  • 性能特点:纯字符数组遍历,效率远高于正则,适合长文本、高频次的批量查找;
  • 适用场景:统计关键词出现次数、提取所有关键词的位置。

六、实战对比与避坑指南

1. 方法选型对比

方法优点缺点适用场景
indexOf()/lastIndexOf() 高效、简单 仅支持简单查找 单个字符 / 子串位置查找
contains() 语义清晰、代码简洁 仅判断存在性 子串存在性校验
matches() 支持复杂正则 性能低、每次编译正则 单次简单正则匹配
Pattern + Matcher 高效、支持复杂规则 代码稍复杂 批量正则匹配、提取子串
indexOf () 循环 高效、可控性强 需手动处理循环 批量子串查找、次数统计

2. 常见避坑点

  • 空指针异常:查找前必须校验字符串是否为null,否则调用indexOf()/contains()会抛出NullPointerException
  • 正则转义:正则中的特殊字符(如.*+)需转义(加\\),否则匹配结果错误;
  • 重复匹配:循环查找时需移动起始位置,避免同一子串被多次匹配;
  • 全字符串匹配matches() 匹配整个字符串,若需匹配子串,正则前后需加.*(如".*Java.*"

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询