contains()是最直接的元素存在性判断方法,语义清晰、代码简洁:arraylist和linkedlist中为o(n)遍历,hashset平均o(1)、treeset为o(log n),使用时需确保自定义类正确重写equals()和hashcode()。

用 contains() 判断元素是否存在最直接
多数 Java 集合(ArrayList、HashSet、LinkedList 等)都实现了 contains() 方法,它内部调用 equals() 比较,语义清晰、代码简洁。
- 对
ArrayList和LinkedList,时间复杂度是O(n),逐个遍历; - 对
HashSet或TreeSet,平均是O(1)或O(log n),快得多; - 务必确保自定义类重写了
equals()和hashCode()(后者仅对哈希类集合必要); - 注意:
contains()只返回boolean,不提供索引或引用。
需要索引或元素本身时用 indexOf() 或循环遍历
indexOf() 是 List 接口的方法,返回首次匹配的下标(找不到为 -1),适合需定位场景;但 Set 和 Map 不支持。
-
ArrayList的indexOf()也是O(n),和contains()底层逻辑一致; - 若需获取匹配对象(比如带额外字段的实体),建议用增强 for 循环 +
break提前退出,避免重复遍历; - Java 8+ 可用
stream().filter().findFirst(),但要注意:小数据量时比传统循环略慢,且无法短路所有中间操作(取决于终端操作); - 别在循环中修改正在遍历的集合,会抛
ConcurrentModificationException。
用 Stream 做条件搜索要小心性能和空值
Stream 写法更函数式,适合组合过滤、映射等逻辑,但不是万能加速器。
-
list.stream().filter(x -> x.getId() == 123).findFirst()返回Optional,必须处理空值,否则可能NoSuchElementException; - 对
ArrayList,流式遍历仍是顺序扫描,没跳过比较; - 若集合已按某字段排序,手动二分查找(如
Collections.binarySearch())比流更快,但要求严格有序且实现Comparable或传入Comparator; - 频繁搜索建议提前转成
HashMap(以搜索字段为 key),把O(n)降为O(1)—— 这比每次搜都用 Stream 更实际。
Map 中按 value 查找不如按 key 查高效
Map 的设计目标是通过 key 快速定位,get(key) 平均 O(1);而按 value 查必须遍历 entrySet(),本质是 O(n)。
立即学习“Java免费学习笔记(深入)”;
- 如果真需要按 value 查,优先考虑是否该把 value 升级为 key(比如反向 Map);
-
map.values().contains(targetValue)看似简洁,但底层仍遍历所有 value,且无法获得对应 key; - 用
entrySet().stream().filter(e -> e.getValue().equals(v)).map(Map.Entry::getKey).findFirst()可同时拿到 key 和 value,但别忘了equals()安全性; - 注意:
ConcurrentHashMap的containsValue()是弱一致性操作,可能查不到刚写入的值。
public class SearchExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// ✅ 推荐:明确意图,安全获取
Optional<Person> found = people.stream()
.filter(p -> "Bob".equals(p.getName()))
.findFirst();
Person result = found.orElse(null);
// ❌ 风险:未判空直接 get()
// Person bad = people.stream().filter(...).findFirst().get();
}
}
class Person {
private String name;
private int age;
Person(String name, int age) { this.name = name; this.age = age; }
String getName() { return name; }
// 注意:此处省略了 equals/hashCode 实现,实际必须补全
}
集合搜索真正难的不是“怎么写”,而是想清楚:这个查找是偶尔一次,还是高频发生?数据规模是几十条,还是百万级?要不要支持模糊、范围或组合条件?这些决定了你该用 contains()、建索引 Map,还是换用 Lucene 这类专用工具。










