Java 实例 – 集合长度(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在 Java 开发中,集合(Collection)是处理数据存储和操作的核心工具。无论是开发小型工具还是复杂系统,开发者都需要频繁与集合打交道。而“集合长度”这一看似基础的概念,实则蕴含了集合类的设计原理、性能优化以及常见陷阱。本文将以 “Java 实例 – 集合长度” 为主题,通过循序渐进的讲解、形象的比喻和实战代码示例,帮助读者深入理解集合长度的获取方法、底层实现逻辑以及实际应用中的注意事项。
基础概念:集合与长度的关联
什么是集合?
集合(Collection)是 Java 集合框架(Java Collection Framework)的核心组件,用于存储、操作和管理一组对象。常见的集合类包括 ArrayList
、LinkedList
、HashSet
等。集合提供了一组通用的接口(如 List
、Set
、Map
),允许开发者以统一的方式处理不同数据结构。
集合长度的定义
集合的“长度”即集合中元素的个数,通常通过 size()
方法获取。例如:
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
System.out.println("集合长度:" + list.size()); // 输出:2
这个简单示例展示了集合长度的基本用法,但背后的实现原理和性能差异需要进一步探讨。
常用集合类详解:如何获取长度?
Java 的集合框架提供了多种实现类,每种类的 size()
方法可能有不同的底层逻辑。以下通过具体案例对比分析。
1. ArrayList:动态数组的高效长度获取
结构比喻:
ArrayList
类似一个“可伸缩的数组”,内部通过一个对象数组存储元素。每当元素数量超过数组容量时,它会自动扩容(默认为原容量的 1.5 倍)。
获取长度:
ArrayList
的 size()
方法直接返回其内部维护的 elementData
数组的长度,因此时间复杂度为 O(1)。
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(10);
arrayList.add(20);
System.out.println(arrayList.size()); // 输出:2
2. LinkedList:链表结构的长度管理
结构比喻:
LinkedList
是一个“双向链表”,每个节点(Node)包含前驱和后继指针。链表的插入和删除操作高效,但随机访问较慢。
获取长度:
Java 的 LinkedList
实际维护了一个 size
变量,因此 size()
方法的时间复杂度同样是 O(1)。
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("Cat");
linkedList.add("Dog");
System.out.println(linkedList.size()); // 输出:2
3. HashSet:哈希表的长度特性
结构比喻:
HashSet
基于哈希表实现,元素存储在 HashMap
的键(Key)中,且不允许重复。
获取长度:
由于哈希表内部维护了一个键的集合,size()
方法直接返回键的数量,时间复杂度为 O(1)。
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(100);
hashSet.add(200);
System.out.println(hashSet.size()); // 输出:2
性能与最佳实践:如何高效获取集合长度?
不同集合类的性能对比
集合类 | size() 时间复杂度 | 适用场景 |
---|---|---|
ArrayList | O(1) | 需要频繁访问元素或遍历 |
LinkedList | O(1) | 需要频繁插入/删除头部或尾部 |
HashSet | O(1) | 需要快速查找和去重 |
优化建议
-
避免冗余计算:
若需多次使用集合长度,可将结果缓存到变量中,避免重复调用size()
方法:int listSize = list.size(); for (int i = 0; i < listSize; i++) { // 遍历逻辑 }
-
空集合的判断:
使用isEmpty()
方法代替size() == 0
,提升代码可读性:if (set.isEmpty()) { System.out.println("集合为空"); }
常见问题与解决方案
1. 遍历集合时修改长度导致的异常
在迭代集合时(如使用 for-each
或 Iterator
),若直接修改集合(如添加/删除元素),会抛出 ConcurrentModificationException
异常。例如:
List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
for (String s : list) {
if (s.equals("B")) {
list.remove(s); // 会抛出异常
}
}
解决方案:
使用 Iterator
的 remove()
方法:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if (s.equals("B")) {
iterator.remove(); // 安全删除
}
}
2. 处理 null
元素的注意事项
某些集合(如 ArrayList
)允许存储 null
元素,但需注意:
null
会被计入长度中;- 多个
null
会被视为重复元素(如HashSet
中只能存在一个null
)。
ArrayList<Object> listWithNull = new ArrayList<>();
listWithNull.add(null);
listWithNull.add(null);
System.out.println(listWithNull.size()); // 输出:2
高级技巧:自定义集合类的长度管理
若需实现自定义集合类,需继承 AbstractCollection
或 AbstractList
,并重写 size()
方法。例如:
public class CustomList<T> extends AbstractList<T> {
private List<T> delegate = new ArrayList<>();
@Override
public T get(int index) {
return delegate.get(index);
}
@Override
public int size() {
return delegate.size();
}
// 其他方法实现
}
通过委托模式,自定义类可复用现有集合的 size()
实现。
结论
通过本文的讲解,读者可以掌握 Java 集合长度的核心概念、实现原理及常见问题的解决方案。无论是基础的 size()
方法调用,还是复杂场景下的性能优化,理解集合类的设计逻辑是关键。建议读者通过实际编码练习加深理解,并结合项目需求选择最合适的集合类型。
记住:集合长度不仅是代码中的一个数值,更是理解数据结构特性的窗口。只有深入掌握其底层机制,才能在开发中游刃有余地应对各种挑战。