当前位置: 首页 > article >正文

Java 中 List 常用类和数据结构详解及案例示范

1. 引言

在 Java 开发中,List 是最常用的数据结构接口之一,它用于存储有序的元素集合,并允许通过索引进行随机访问。电商系统中,如购物车、订单列表和商品目录等功能都依赖 List 进行数据管理。选择适当的 List 实现类能够显著提高性能、代码可维护性和可扩展性。

本文将以电商交易系统为案例,详细讲解 Java 中 List 常用实现类的底层数据结构、应用场景以及如何选择合适的 List 实现类,必要时使用类图或时序图辅助说明。

2. 问题描述

在电商系统中,订单、商品列表、购物车等操作都需要使用 List 来存储数据。不同的场景下有不同的性能需求:

  • 订单列表通常需要支持频繁的增删改查操作。
  • 购物车需要高效地增加或移除商品,并需要支持并发修改。
  • 商品列表通常比较稳定,查找商品的效率比更新商品更为重要。

为此,开发人员需要根据不同的需求,选择合适的 List 实现类。

3. List 常用实现类

Java 中常见的 List 实现类包括:

  • ArrayList
  • LinkedList
  • CopyOnWriteArrayList

每个类都有不同的适用场景和底层实现。接下来,我们将详细介绍这些实现类,并通过电商系统中的具体问题展示它们的区别与应用场景。

3.1 ArrayList

3.1.1 问题场景

在电商系统中,商品展示页面通常需要快速加载商品数据,并允许用户分页查看。此时需要一个能快速随机访问元素的集合,且商品数据通常是稳定的,不会频繁更新。

3.1.2 解决方式:ArrayList 的底层结构

ArrayList 是基于动态数组实现的 List,它的优点是能够快速随机访问元素。ArrayList 的底层是一个数组,当数组容量不够时,会自动扩容。以下是 ArrayList 的核心特点:

  • 随机访问效率高:因为底层是数组,通过索引访问元素的时间复杂度是 O(1)。
  • 增删元素效率低:当从中间插入或删除元素时,需要移动数组中的部分元素,时间复杂度为 O(n)。
  • 动态扩容:当数组容量不足时,ArrayList 会自动扩容,一般扩容为原容量的 1.5 倍。
List<String> products = new ArrayList<>();
products.add("Laptop");
products.add("Smartphone");
products.add("Headphones");

// 随机访问商品
String product = products.get(1);  // 获取第二个商品,时间复杂度 O(1)
3.1.3 底层实现

ArrayList 的内部通过一个数组 elementData 实现,当我们向 ArrayList 添加元素时,如果数组容量不足,ArrayList 会调用 grow() 方法扩展数组的大小,典型的扩容因子为 1.5 倍。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);  // 扩容1.5倍
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    elementData = Arrays.copyOf(elementData, newCapacity);
}
3.1.4 适用场景

ArrayList 非常适合以下场景:

  • 需要频繁的随机访问(如分页查询、商品展示)。
  • 插入和删除操作较少。
3.1.5 类图辅助说明

在这里插入图片描述

3.2 LinkedList

3.2.1 问题场景

在购物车功能中,用户可能会频繁地添加和移除商品,特别是从列表的开头或中间移除。此时,ArrayList 并不适用,因为它在移除操作时需要移动大量元素。

3.2.2 解决方式:LinkedList 的底层结构

LinkedList 是基于双向链表实现的 List,它允许快速地在头部或尾部插入和删除元素,时间复杂度为 O(1)。它不需要像 ArrayList 那样移动元素,因此在需要频繁插入或删除元素的场景下非常高效。

List<String> cart = new LinkedList<>();
cart.add("Laptop");
cart.add("Smartphone");

// 在头部插入商品
cart.add(0, "Headphones");

// 删除第一个商品
cart.remove(0);
3.2.3 底层实现

LinkedList 底层是一个双向链表,每个节点包含前驱和后继节点的引用。与 ArrayList 不同的是,LinkedList 的插入和删除操作不需要移动元素,因此效率更高。

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
    
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
3.2.4 适用场景

LinkedList 适用于以下场景:

  • 需要频繁地在集合的头部或尾部插入和删除元素。
  • 插入和删除的效率比随机访问更重要。
3.2.5 类图辅助说明

在这里插入图片描述

3.3 CopyOnWriteArrayList

3.3.1 问题场景

在电商系统中,可能会有多用户同时操作购物车或订单列表。这种场景下,普通的 ArrayListLinkedList 无法保证线程安全,而手动加锁会影响性能。

3.3.2 解决方式:CopyOnWriteArrayList 的底层结构

CopyOnWriteArrayList 是一个线程安全的 List 实现,它的核心原理是“写时复制”(Copy-On-Write)。当写操作(如添加、修改、删除)发生时,CopyOnWriteArrayList 会创建数组的一个副本,在副本上进行修改,从而避免了并发冲突。由于每次写操作都会创建新的副本,因此它适用于读多写少的场景。

List<String> safeCart = new CopyOnWriteArrayList<>();
safeCart.add("Laptop");
safeCart.add("Smartphone");

// 并发读写
safeCart.forEach(item -> System.out.println(item));
3.3.3 底层实现

CopyOnWriteArrayList 的底层实现是基于数组的,但它通过在修改时创建新数组,确保了线程安全。读取操作可以不加锁,因为数组不会被修改。

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}
3.3.4 适用场景

CopyOnWriteArrayList 适合以下场景:

  • 读多写少的高并发环境。
  • 对数据一致性要求高,但写操作较少的场景。
3.3.5 类图辅助说明

在这里插入图片描述

4. List 实现类的性能对比

实现类底层结构插入/删除效率随机访问效率线程安全性适用场景
ArrayList动态数组需要快速随机访问,且插入删除操作较少
LinkedList双向链表频繁插入或删除元素的场景
CopyOnWriteArrayList动态数组(写时复制)中等读多写少的并发场景,如订单列表或购物车的并发操作

5. 总结

在电商系统中,不同的场景对 List 的需求不同。ArrayList 适用于数据读取频繁但不经常修改的场景;LinkedList 适合需要频繁插入、删除操作的场景;CopyOnWriteArrayList 则在多线程高并发的场景中表现出色。开发人员应根据具体需求选择合适的 List 实现,以提高系统的性能和稳定性。


http://www.kler.cn/news/309758.html

相关文章:

  • 基于python+django+vue的外卖管理系统
  • java循环遍历树状结构对象并转换成另外树状结构对象
  • 6.安卓逆向-安卓开发基础adb工具
  • 学习贵在善假于物
  • 什么是科技与艺术相结合的异形创意圆形(饼/盘)LED显示屏
  • YooAsset基础操作及热更
  • 自监督的主要学习方法
  • Web植物管理系统-下位机部分
  • Facebook主页,广告账户,BM被封分别怎么解决?
  • sicp每日一题[2.17]
  • Ubuntu上如何使用sh文件更新CMake
  • 【二十一】【QT开发应用】ListWiddget图标模式
  • yolo自动化项目实例解析(二)ui页面整理
  • 组件上的v-model(数据传递),props验证,自定义事件,计算属性
  • 家电制造的隐形守护者:矫平机确保材料完美无瑕
  • Linux 调用write()函数后,内核一般多久将数据写入磁盘
  • Java轻量级测试框架的实现与使用 总篇
  • 【资料分析】刷题日记1
  • 保护您的企业免受网络犯罪分子侵害的四个技巧
  • 【运维监控】Prometheus+grafana监控flink运行情况
  • SpringBoot2:web开发常用功能实现及原理解析-@ControllerAdvice实现全局异常统一处理
  • [苍穹外卖]-10WebSocket入门与实战
  • SpringBoot整合WebSocket实现消息推送或聊天功能示例
  • 从头开始学MyBatis—02基于xml和注解分别实现的增删改查
  • (java+Seleniums3)自动化测试实战2
  • ssh远程连接try1账号切换tips
  • 宝兰德MCP系列介绍 ①:中间件管理能力全线升级,驱动企业数字化管理效能提升
  • node.js 完全卸载和下载配置
  • 五种数据库特性对比(Redis/Mysql/SQLite/ES/MongoDB)
  • 780nm 扫地机器人模组:科技引领智能清洁新潮流