
本文介绍一种实用算法,用于在由多个字符串片段组成的 List 中精确查找跨片段的目标子串(如 "[{searched_placeholder}]"),并返回其在列表中的起始和结束下标位置。
本文介绍一种实用算法,用于在由多个字符串片段组成的 `list
在实际开发中,我们常遇到文本被预分割为 List<string></string> 的场景(例如模板引擎、流式解析或内存受限的分块处理)。此时,待搜索的目标字符串(如占位符 "[{searched_placeholder}]")可能横跨多个列表元素,无法通过单个 String.contains() 或 indexOf() 直接定位其在列表中的逻辑位置。本教程提供一种清晰、可靠且易于理解的解决方案。
核心思路
将列表按顺序拼接成完整字符串(使用 StringBuilder 避免频繁对象创建),再通过两次扫描确定边界:
-
正向扫描:逐项追加,一旦拼接后的字符串首次包含目标子串,记录当前索引为
endIndex; -
反向收缩:从
[0, endIndex]范围内逐步移除前缀,当移除某一项后目标子串不再存在,说明该项正是起始点(即startIndex)。
✅ 注意:该算法假设目标子串在拼接后字符串中唯一存在;若需支持多匹配,可扩展为返回
List<int></int>。
完整实现代码
import java.util.*;
public class ListSubstringLocator {
/**
* 在分段字符串列表中查找目标子串的起始与结束索引(含)
* @param fragments 字符串片段列表(不可为 null)
* @param target 待搜索的目标子串(不可为 null)
* @return int[2]:{startIndex, endIndex};未找到则返回 {-1, -1}
*/
public static int[] findFragmentRange(List<string> fragments, String target) {
if (fragments == null || target == null || fragments.isEmpty()) {
return new int[]{-1, -1};
}
StringBuilder sb = new StringBuilder();
int endIndex = -1;
// 第一次遍历:确定结束位置(首次完整包含 target 的最右索引)
for (int i = 0; i 0) {
temp.delete(0, fragments.get(i - 1).length());
}
if (temp.indexOf(target) == -1) {
// 上一轮(i-1)仍包含,故起始为 i-1
startIndex = i - 1;
break;
}
// 若 i == endIndex 且仍包含,则起始即为 endIndex(单片段匹配)
if (i == endIndex) {
startIndex = endIndex;
}
}
return new int[]{startIndex, endIndex};
}
// 示例用法
public static void main(String[] args) {
List<string> fragments = new ArrayList();
fragments.add("This is a ");
fragments.add("[{searched");
fragments.add("_placeholder}]");
fragments.add(" in this string.");
int[] range = findFragmentRange(fragments, "searched_placeholder");
System.out.printf("Start index: %d, End index: %d%n", range[0], range[1]);
// 输出:Start index: 1, End index: 2
// 验证结果:拼接 fragments[1] + fragments[2] 确实包含目标
String reconstructed = fragments.get(1) + fragments.get(2);
System.out.println("Reconstructed fragment: \"" + reconstructed + "\"");
System.out.println("Contains target: " + reconstructed.contains("searched_placeholder"));
}
}</string></string>
关键注意事项
- 性能权衡:时间复杂度为 O(n·m),其中 n 是列表长度,m 是平均字符串长度;适用于中小规模数据(
- 边界安全:代码已处理空列表、null 输入、未匹配等异常情况,生产环境可直接集成。
-
语义明确:
startIndex和endIndex均为 列表下标(0-based),表示目标子串至少部分字符所在的第一个和最后一个片段位置。 -
扩展建议:若需支持正则匹配、大小写不敏感或重叠匹配,应在
sb.indexOf(...)处替换为Pattern.compile(...).matcher(sb).find()并同步维护偏移映射。
掌握此方法,即可稳健应对模板渲染、日志分片检索、协议报文解析等真实场景中的“跨块搜索”问题。










