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;
}

⚠️ 注意:这里假设 listsearch 都不为 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


原始标题:Searching for a String in an ArrayList | Baeldung