Java简单搜索应优先用ArrayList/HashMap配合stream().filter()实现内存模糊匹配,TreeSet结合subSet()支持大小写不敏感前缀搜索,需预处理null和空值并避免无效搜索。

Java里做简单搜索,核心是别一上来就写数据库查询或引入Elasticsearch——多数场景下,用 ArrayList 或 HashMap 配合 stream().filter() 就够了,既快又不用额外依赖。
用 stream().filter() 做内存中字符串模糊匹配
适合数据量小(
- 必须先确保字段已加载到内存,不能边查边从数据库拉
-
filter()里别用toLowerCase()多次转换,提前把关键词和字段都转好 - 避免在
filter()中调用远程接口或 IO 操作,会阻塞整个流
Listresults = users.stream() .filter(u -> u.getName() != null && u.getName().toLowerCase().contains(keyword.toLowerCase())) .collect(Collectors.toList());
用 TreeSet 实现前缀自动补全式搜索
当用户输入“zhang”想看到所有姓张的用户时,TreeSet 的 subSet() 比遍历快得多,前提是数据可排序且字段唯一性可控。
- 初始化时必须用
String.CASE_INSENSITIVE_ORDER,否则大小写敏感会漏结果 - 只适用于单字段精确前缀(如用户名、编号),不支持中间匹配(如“%hang%”)
- 插入新数据后要重新构建
TreeSet,不适合高频写入场景
TreeSetnameIndex = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); nameIndex.addAll(users.stream().map(User::getName).filter(Objects::nonNull).collect(Collectors.toList())); Set candidates = nameIndex.subSet("zhang", true, "zhang\uFFFF", false);
避免踩 NullPointerException 和空集合陷阱
真实项目里最常崩的不是算法,而是没处理好 null 和空集合。尤其当搜索字段来自 JSON 解析或数据库 NULL 值时。
立即学习“Java免费学习笔记(深入)”;
- 永远对搜索字段做
Objects.nonNull()或StringUtils.isNotBlank()判断,别信注释里的“必不为空” - 返回值统一用
Collections.emptyList(),别返回null,下游调用方不会每处都判空 - 如果用 MyBatis,
必须写全,少一个条件就可能生成WHERE name LIKE '%'全表扫
真正难的不是写出能跑的搜索,而是判断该不该搜——比如用户输了个空格、纯数字、或长度小于2的词,这时候直接返回空比硬搜更合理。边界逻辑比主流程更容易出问题。










