在 Java 日常开发中,经常会遇到需要在集合中寻找第一个匹配元素的需求,通常会使用 for 循环、Stream API来实现。
本篇文章介绍一个封装 for 循环实现的两个工具方法。
完整代码:
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
public class CollUtils {
public static <T> T findOne(Iterable<T> collection, Predicate<T> filter) {
if (collection != null) {
for (T t : collection) {
if (filter.test(t)) {
return t;
}
}
}
return null;
}
public static <T> T findOneByField(Iterable<T> collection, Function<T,?> field, Object fieldValue) {
return findOne(collection, (t) -> {
Object value = field.apply(t);
return Objects.equals(value, fieldValue);
});
}
}
● findOne:使用 Predicate 过滤,返回第一个匹配或 null。
● findOneByField:按字段值查找,内部复用 findOne,用 Objects.equals 处理 null。
使用示例
public class Person {
private String name;
private int age;
private String id;
// 构造函数和 getter...
}
示例:
import java.util.Arrays;
import java.util.List;
List<Person> people = Arrays.asList(
new Person("Alice", 25, "A001"),
new Person("Bob", 30, "B002"),
new Person("Charlie", 35, "C003")
);
// 按条件过滤
Person adult = CollUtils.findOne(people, p -> p.getAge() > 28); // Bob
// 按字段查找
Person byId = CollUtils.findOneByField(people, Person::getId, "C003"); // Charlie
与 Stream API 对比
Stream 等效:
Person adultStream = people.stream()
.filter(p -> p.getAge() > 28)
.findFirst()
.orElse(null);
两者均为短路操作,不会全遍历。但方法更简洁(单调用 vs. 链式),轻量(无流开销),适合小中型集合。基准测试显示,for 循环在顺序处理中更快(如 JMH 测试:for ~3ms vs. Stream ~12ms 在百万级数据)。
优势与注意事项
优势:
● 简洁:更短代码
● 性能:低开销,适合高频调用
● 灵活:泛型 + Lambda,易扩展
● 零依赖:JDK 8+ 即可
注意:
● 返回 null 易 NPE,建议 Optional 包装
● 大集合用 Stream 并行化更好
● 非线程安全(依赖集合)
总之是一种新的选择,单纯分享一下写法。