Java 实例 – 集合长度(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在 Java 开发中,集合(Collection)是处理数据存储和操作的核心工具。无论是开发小型工具还是复杂系统,开发者都需要频繁与集合打交道。而“集合长度”这一看似基础的概念,实则蕴含了集合类的设计原理、性能优化以及常见陷阱。本文将以 “Java 实例 – 集合长度” 为主题,通过循序渐进的讲解、形象的比喻和实战代码示例,帮助读者深入理解集合长度的获取方法、底层实现逻辑以及实际应用中的注意事项。


基础概念:集合与长度的关联

什么是集合?

集合(Collection)是 Java 集合框架(Java Collection Framework)的核心组件,用于存储、操作和管理一组对象。常见的集合类包括 ArrayListLinkedListHashSet 等。集合提供了一组通用的接口(如 ListSetMap),允许开发者以统一的方式处理不同数据结构。

集合长度的定义

集合的“长度”即集合中元素的个数,通常通过 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 倍)。

获取长度
ArrayListsize() 方法直接返回其内部维护的 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() 时间复杂度适用场景
ArrayListO(1)需要频繁访问元素或遍历
LinkedListO(1)需要频繁插入/删除头部或尾部
HashSetO(1)需要快速查找和去重

优化建议

  1. 避免冗余计算
    若需多次使用集合长度,可将结果缓存到变量中,避免重复调用 size() 方法:

    int listSize = list.size();  
    for (int i = 0; i < listSize; i++) {  
        // 遍历逻辑  
    }  
    
  2. 空集合的判断
    使用 isEmpty() 方法代替 size() == 0,提升代码可读性:

    if (set.isEmpty()) {  
        System.out.println("集合为空");  
    }  
    

常见问题与解决方案

1. 遍历集合时修改长度导致的异常

在迭代集合时(如使用 for-eachIterator),若直接修改集合(如添加/删除元素),会抛出 ConcurrentModificationException 异常。例如:

List<String> list = new ArrayList<>(Arrays.asList("A", "B"));  
for (String s : list) {  
    if (s.equals("B")) {  
        list.remove(s); // 会抛出异常  
    }  
}  

解决方案
使用 Iteratorremove() 方法:

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  

高级技巧:自定义集合类的长度管理

若需实现自定义集合类,需继承 AbstractCollectionAbstractList,并重写 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() 方法调用,还是复杂场景下的性能优化,理解集合类的设计逻辑是关键。建议读者通过实际编码练习加深理解,并结合项目需求选择最合适的集合类型。

记住:集合长度不仅是代码中的一个数值,更是理解数据结构特性的窗口。只有深入掌握其底层机制,才能在开发中游刃有余地应对各种挑战。

最新发布