String.indexOf()仅适用于单关键词、大小写敏感、无空格分词的极简场景;复杂需求需正则或分词;倒排索引用HashMap可行但需小写归一化、过滤停用词;通配查询宜用TreeSet.tailSet优化;Lucene适合复杂搜索,轻量场景自研更优。
用 String.indexOf() 做基础关键词匹配够不够?
够,但仅限单关键词、大小写敏感、无空格分词的极简场景。比如用户输入 "error",你想从日志行中快速判断是否包含——直接调用 line.indexOf("error") != -1 是最快路径。
但一旦出现以下情况,indexOf() 就开始漏匹配或误匹配:
- 用户搜
"http status",实际文本是"HTTP Status: 500"(大小写 + 中间空格) - 用户搜
"log",结果把"logging"和"catalog"全捞出来 - 需要同时匹配多个词,且要求它们“挨得近”(比如在 10 字内共现)
这时候就得上正则或预处理分词,而不是硬扛 indexOf()。
内存里存文档,用 HashMap> 建倒排索引行不行?
行,适合千条以内文档、单机运行、不追求实时更新的场景。核心思路是:对每篇文档做分词(比如按空白+标点切),把每个词映射到它出现过的文档 ID 列表。
立即学习“Java免费学习笔记(深入)”;
示例结构:
Map<String, List> invertedIndex = new HashMap();
invertedIndex.put("java", Arrays.asList(1, 5, 8)); // 文档1/5/8含"java"
invertedIndex.put("search", Arrays.asList(2, 5)); // 文档2/5含"search"
注意几个易错点:
- 分词时别忘了小写归一化(
word.toLowerCase()),否则"Java"和"java"被当两个词 - 停用词(如
"the","a")不入索引,否则索引膨胀且无检索价值 - 文档 ID 最好用
int而非String,省内存、查得快 - 如果要支持“短语查询”(如
"full text"),光靠这个结构不够,还得存每个词在文档内的位置列表
用户输入带通配符(如 "jav*")怎么处理?
Java 标准库不直接支持前缀通配搜索,得自己扫倒排索引的 key 集合。别用 keySet().stream().filter(...),一查就遍历全量,O(n) 太慢。