Java 查找字符串最后一次出现的位置

在 Java 开发中,查找字符串中字符或子串最后一次出现的位置是高频需求(如解析文件路径、提取后缀名、处理 URL 等场景)。核心依赖 String 类的 lastIndexOf() 方法,该方法提供多种重载形式,适配不同查找场景。本文通过实例详解所有用法、返回规则及实际应用场景。

一、核心方法:lastIndexOf() 重载说明

String 类提供 4 个 lastIndexOf() 重载方法,均返回目标字符 / 子串在原字符串中最后一次出现的索引(索引从 0 开始);若未找到,返回 -1
 
方法签名功能说明
int lastIndexOf(int ch) 查找单个字符(ch 为字符的 Unicode 编码,可直接传字符或对应 int 值)最后一次出现的索引。
int lastIndexOf(int ch, int fromIndex) 从指定索引 fromIndex 开始向前查找(包含 fromIndex),返回字符 ch 最后一次出现的索引。
int lastIndexOf(String str) 查找子字符串 str 最后一次出现的索引(子串需完整匹配)。
int lastIndexOf(String str, int fromIndex) 从指定索引 fromIndex 开始向前查找,返回子串 str 最后一次出现的索引。

关键规则:

  1. 索引从 0 开始(如 "abc" 中 'a' 索引为 0,'c' 为 2)。
  2. fromIndex 超出范围时:
    • 若 fromIndex >= 字符串长度:等效于从字符串末尾开始查找。
    • 若 fromIndex < 0:等效于从索引 0 开始查找(即全串查找,但仍返回最后一次出现位置)。
  3. 查找空字符串 "" 时,返回字符串的长度(如 "test".lastIndexOf ("") → 4)。

二、实例场景详解(附完整代码)

场景 1:查找单个字符最后一次出现的位置

需求:

已知字符串 str = "Hello, Java! Java is easy.",查找字符 'a' 和 '!' 最后一次出现的位置。

代码实现:

public class LastIndexOfDemo {
    public static void main(String[] args) {
        String str = "Hello, Java! Java is easy.";
        
        // 1. 查找字符 'a' 最后一次出现的位置
        int indexA = str.lastIndexOf('a');
        System.out.println("字符 'a' 最后一次出现的索引:" + indexA); // 输出:18(对应第二个 Java 中的 'a')
        
        // 2. 查找字符 '!' 最后一次出现的位置
        int indexExclaim = str.lastIndexOf('!');
        System.out.println("字符 '!' 最后一次出现的索引:" + indexExclaim); // 输出:9(仅出现一次)
        
        // 3. 查找不存在的字符(返回 -1)
        int indexZ = str.lastIndexOf('z');
        System.out.println("字符 'z' 最后一次出现的索引:" + indexZ); // 输出:-1
    }
}
 

场景 2:查找子字符串最后一次出现的位置

需求:

在上述字符串中,查找子串 "Java" 和 "is" 最后一次出现的位置。

代码实现: 

public class LastIndexOfSubstringDemo {
    public static void main(String[] args) {
        String str = "Hello, Java! Java is easy.";
        
        // 1. 查找子串 "Java" 最后一次出现的位置(子串首字符索引)
        int indexJava = str.lastIndexOf("Java");
        System.out.println("子串 \"Java\" 最后一次出现的索引:" + indexJava); // 输出:12(第二个 Java 的 'J' 索引)
        
        // 2. 查找子串 "is" 最后一次出现的位置
        int indexIs = str.lastIndexOf("is");
        System.out.println("子串 \"is\" 最后一次出现的索引:" + indexIs); // 输出:17
        
        // 3. 查找不存在的子串(返回 -1)
        int indexPython = str.lastIndexOf("Python");
        System.out.println("子串 \"Python\" 最后一次出现的索引:" + indexPython); // 输出:-1
    }
}
 

场景 3:从指定位置向前查找(含 fromIndex 参数)

需求:

在字符串 str = "abacadaeaf" 中,从索引 8 开始向前查找字符 'a',从索引 5 开始向前查找子串 "ada"

代码实现:

public class LastIndexOfFromIndexDemo {
    public static void main(String[] args) {
        String str = "abacadaeaf"; // 索引:0:a,1:b,2:a,3:c,4:a,5:d,6:a,7:e,8:a,9:f
        
        // 1. 从索引 8 开始向前查找 'a'(包含索引8)
        int indexA1 = str.lastIndexOf('a', 8);
        System.out.println("从索引8向前查找 'a' 的位置:" + indexA1); // 输出:8(索引8本身是 'a')
        
        // 2. 从索引 7 开始向前查找 'a'(不包含索引8)
        int indexA2 = str.lastIndexOf('a', 7);
        System.out.println("从索引7向前查找 'a' 的位置:" + indexA2); // 输出:6
        
        // 3. 从索引 5 开始向前查找子串 "ada"(子串需完整匹配)
        int indexAda = str.lastIndexOf("ada", 5);
        System.out.println("从索引5向前查找 \"ada\" 的位置:" + indexAda); // 输出:4(子串 "ada" 对应索引4-6,但 fromIndex=5,仅匹配4-5?不,子串长度3,从5向前找,实际匹配索引4-6是否在范围,这里返回4)
        
        // 4. fromIndex 超出字符串长度(等效于末尾查找)
        int indexA3 = str.lastIndexOf('a', 20);
        System.out.println("fromIndex=20 查找 'a' 的位置:" + indexA3); // 输出:8(最后一个 'a')
    }
}
 

场景 4:实际应用:提取文件后缀名 / 文件名

需求:

给定文件路径字符串,通过 lastIndexOf() 提取文件名和后缀名(开发中常见场景)。

代码实现:

public class FilePathParseDemo {
    public static void main(String[] args) {
        String filePath = "D:/document/project/java/StringDemo.java";
        
        // 1. 提取文件名(最后一个 "/" 之后的内容)
        int lastSlashIndex = filePath.lastIndexOf("/");
        String fileName = filePath.substring(lastSlashIndex + 1);
        System.out.println("文件名:" + fileName); // 输出:StringDemo.java
        
        // 2. 提取后缀名(最后一个 "." 之后的内容)
        int lastDotIndex = filePath.lastIndexOf(".");
        if (lastDotIndex != -1) { // 确保存在后缀名
            String suffix = filePath.substring(lastDotIndex + 1);
            System.out.println("文件后缀名:" + suffix); // 输出:java
        } else {
            System.out.println("该文件无后缀名");
        }
        
        // 3. 处理 Windows 路径(反斜杠 "\\",需转义)
        String windowsPath = "C:\\Users\\test\\photo.png";
        int lastBackslashIndex = windowsPath.lastIndexOf("\\");
        String windowsFileName = windowsPath.substring(lastBackslashIndex + 1);
        System.out.println("Windows 路径文件名:" + windowsFileName); // 输出:photo.png
    }
}
 

三、注意事项(避坑指南)

  1. 空值与空字符串处理
    • 传入 null 作为子串(如 str.lastIndexOf(null)):抛出 NullPointerException,需提前判空。
    • 传入空字符串 "":返回字符串长度(如 "test".lastIndexOf("") → 4),这是 Java 的设计规则,无需特殊处理。
  2. 区分大小写
    • lastIndexOf() 是大小写敏感的(如 "Java".lastIndexOf("java") → -1)。
    • 若需忽略大小写,需先将原字符串和目标串统一转为大写或小写(如 str.toLowerCase().lastIndexOf("java"))。
  3. 索引越界问题
    • 提取子串时(如 substring()),需先判断 lastIndexOf() 返回值是否为 -1(避免未找到目标时导致 StringIndexOutOfBoundsException)。
    • 示例:
      // 错误写法(未判断 -1)
      String suffix = filePath.substring(filePath.lastIndexOf(".") + 1); // 无后缀时会报错
      
      // 正确写法
      int dotIndex = filePath.lastIndexOf(".");
      String suffix = dotIndex != -1 ? filePath.substring(dotIndex + 1) : "无后缀";
      
       
  4. Unicode 字符查找
    • lastIndexOf(int ch) 中 ch 是 Unicode 编码,可直接传入字符(如 '中')或对应的 Unicode 数值(如 '\u4e2d')。
    • 示例:"中国,中国".lastIndexOf('中') → 3(索引 0 和 3 均为 ' 中 ',返回最后一个)。

四、总结

lastIndexOf() 是 Java 处理字符串的核心方法,核心用途是从后向前查找字符 / 子串的位置,配合 substring() 可实现文件路径解析、后缀提取、数据清洗等实际需求。使用时需注意:
 
  • 未找到目标返回 -1,需提前判断避免索引越界;
  • 区分大小写,按需统一转换;
  • 处理 null 参数,避免空指针异常。

posted on 2025-12-03 16:24  coding博客  阅读(0)  评论(0)    收藏  举报