1. 概述
本文将探讨 在 ArrayList
中查找字符串的多种方式。我们的目标是:判断某个非空字符序列是否存在于列表中的任意元素中,并返回所有匹配项组成的列表。
这个需求在实际开发中很常见,比如日志过滤、关键词搜索等场景。虽然看起来简单,但不同实现方式在可读性、性能和兼容性上差异明显,值得我们对比分析。
2. 基础循环
最原始但也最直观的方式是使用增强 for 循环配合 String.contains()
方法进行遍历匹配。
✅ 优点:逻辑清晰,兼容所有 Java 版本
❌ 缺点:代码略冗长,函数式表达能力弱
public List<String> findUsingLoop(String search, List<String> list) {
List<String> matches = new ArrayList<String>();
for(String str: list) {
if (str.contains(search)) {
matches.add(str);
}
}
return matches;
}
⚠️ 注意:这里假设 list
和 search
都不为 null
,实际项目中建议增加空值校验,避免踩坑 NullPointerException
。
3. 使用 Stream API
Java 8 引入的 Stream API 提供了更简洁、声明式的写法。通过 filter()
+ collect()
组合,一行代码就能完成过滤操作。
✅ 优点:代码简洁,可读性强,支持链式调用
✅ 推荐指数:⭐⭐⭐⭐⭐
public List<String> findUsingStream(String search, List<String> list) {
List<String> matchingElements = list.stream()
.filter(str -> str.trim().contains(search))
.collect(Collectors.toList());
return matchingElements;
}
📌 小贴士:示例中加了 trim()
是为了处理前后空格的模糊匹配场景,根据业务需要决定是否保留。
💡 提示:
Collectors.toList()
返回的是ArrayList
,无需担心底层实现问题。
4. 第三方库方案
如果你的项目还在使用 Java 7 或更早版本,无法使用 Stream API,可以考虑引入成熟的第三方集合工具库,比如 Apache Commons Collections 和 Google Guava。
先添加依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.5.0-M2</version>
</dependency>
4.1. Apache Commons Collections
使用 IterableUtils.filteredIterable()
配合 Predicate
实现过滤,最后转为 List
。
public List<String> findUsingCommonsCollection(String search, List<String> list) {
Iterable<String> result = IterableUtils.filteredIterable(list, new Predicate<String>() {
public boolean evaluate(String listElement) {
return listElement.contains(search);
}
});
return IteratorUtils.toList(result.iterator());
}
⚠️ 老式匿名内部类写法略显臃肿,如果项目支持 Lambda,建议升级版本而非强行使用旧库。
4.2. Google Guava
Guava 提供了更优雅的 Iterables.filter()
方法,配合内置的 Predicates.containsPattern()
可以简单粗暴地完成任务。
public List<String> findUsingGuava(String search, List<String> list) {
Iterable<String> result = Iterables.filter(list, Predicates.containsPattern(search));
return Lists.newArrayList(result.iterator());
}
✅ Guava 的优势在于 API 设计简洁,且 Predicates
工具类提供了丰富的条件构造方法,适合复杂过滤逻辑。
📌 注意:
containsPattern()
实际使用的是正则匹配,如果search
包含特殊字符(如.
,*
),可能产生意外结果。如需普通子串匹配,应改用:Predicates.containsPattern(Pattern.quote(search))
5. 总结
方式 | 是否推荐 | 适用场景 |
---|---|---|
基础 for 循环 | ⚠️ | Java 7- 环境,无外部依赖 |
Stream API | ✅✅✅ | Java 8+,现代项目首选 |
Commons Collections | ⚠️ | 老项目维护,无法升级 JDK |
Google Guava | ✅ | 已引入 Guava 的项目,功能丰富 |
📌 最终建议:
- 新项目一律使用 Stream API,简洁高效。
- 若已引入 Guava 且逻辑复杂,可考虑其工具类。
- 避免为了一个简单功能引入新依赖,别让项目“过度工程化”。
🔚 示例代码已上传至 GitHub:https://github.com/baeldung/java-collections-search