当前位置:首页 > 后端开发 > 正文

java list怎么使用方法

Java List通过add()添加元素,get(index)获取,size()查长度,可用

Java中的List是java.util包下的核心接口之一,用于表示有序、可重复的元素集合,它继承了Collection接口的所有特性,并额外提供了基于索引的精确控制能力,以下是对其使用方法的系统性解析:


核心特征与常见实现类

特性 描述
有序性 元素按插入顺序存储,可通过索引快速访问
允许重复 同一元素可多次出现
允许null值 可以包含null元素
动态扩容 多数实现类支持自动扩容(如ArrayList)
多种底层结构 不同实现类采用数组/链表/栈等不同数据结构

主流实现类对比表

实现类 底层结构 增删效率 随机访问效率 适用场景 线程安全
ArrayList 动态数组 尾部快

头部慢

O(1) 频繁随机访问/少量增删
LinkedList 双向链表 任意位置快 O(n) 频繁头尾操作/大数据量插入删除
Vector 动态数组 同ArrayList O(1) 古老线程安全版本(现推荐改用CopyOnWriteArrayList)
CopyOnWriteArrayList 写时复制数组 写入开销大 O(1) 高并发读多写少场景


核心方法详解(以ArrayList为例)

基础操作

import java.util.ArrayList; import java.util.List; public class ListDemo { public static void main(String[] args) { // 创建List实例 List<String> fruits = new ArrayList<>(); // 钻石操作符简化泛型声明 // 添加元素 fruits.add("Apple"); // 尾部追加 → [Apple] fruits.add("Banana"); // → [Apple, Banana] fruits.add(1, "Orange"); // 指定索引插入 → [Apple, Orange, Banana] // 获取元素 System.out.println("第二个元素: " + fruits.get(1)); // 输出 Orange // 修改元素 fruits.set(0, "Pear"); // 替换索引0元素 → [Pear, Orange, Banana] // 删除元素 fruits.remove(1); // 删除索引1 → [Pear, Banana] fruits.remove("Banana"); // 删除对象 → [Pear] // 判断存在性 boolean hasApple = fruits.contains("Apple"); // false } }

批量操作

方法 功能 示例
addAll(Collection<? extends E> c) 追加整个集合 fruits.addAll(Arrays.asList("Grape", "Melon"))
subList(int fromIndex, int toIndex) 返回指定区间的子视图(原地修改影响源) List<String> sub = fruits.subList(0, 2)
clear() 清空列表 fruits.clear()

特殊操作技巧

  • 交换元素:需借助临时变量 String temp = fruits.get(i); fruits.set(i, fruits.get(j)); fruits.set(j, temp);
  • 倒序遍历:结合Collections.reverse()或手动逆序索引
  • 固定大小限制:创建时指定初始容量避免频繁扩容 new ArrayList<>(initialCapacity); // 推荐设置为预期大小的120%


关键实现类的特性差异

ArrayList vs LinkedList性能测试

操作类型 ArrayList耗时 LinkedList耗时 原因分析
尾部添加 (最快) 数组尾部直接赋值
头部插入 (最慢) 数组需移动后续所有元素
中间插入 链表只需修改前后指针
根据索引随机访问 (最快) (最慢) 数组通过CPU缓存预取优化
遍历全部元素 (最快) 链表跳跃式访问无内存局部性

Vector的特殊性

  • 历史遗留的线程安全类,所有公共方法均使用synchronized修饰
  • 已过时!现代开发推荐:
    • 单线程环境:ArrayList
    • 多线程环境:CopyOnWriteArrayList(读多写少)或手动同步Collections.synchronizedList(new ArrayList<>())


高级用法示例

排序与二分查找

List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 3, 8, 1)); Collections.sort(numbers); // [1, 3, 5, 8] int index = Collections.binarySearch(numbers, 5); // 返回2(找到的位置)

自定义比较器排序

List<Student> students = ...; // Student类需实现Comparable或提供Comparator students.sort((a, b) -> a.getAge() b.getAge()); // 按年龄升序

不可变列表创建

List<String> immutableList = List.of("A", "B", "C"); // Java 9+ // 尝试修改会抛出UnsupportedOperationException immutableList.add("D"); // Error!


注意事项与最佳实践

  1. 避免空指针异常

    java list怎么使用方法 第1张

    • 始终检查size()后再通过索引访问元素
    • 使用isEmpty()判断空列表而非size()==0
  2. 迭代器安全

    java list怎么使用方法 第2张

    • 结构化修改(遍历时删除/添加)会导致ConcurrentModificationException
    • 解决方案:使用Iterator的remove()方法或改用for循环倒序删除
    • 内存优化

      java list怎么使用方法 第3张

      • ArrayList初始容量设为预计大小的120%可减少扩容次数
      • 高频插入/删除场景优先考虑LinkedList
      • 线程安全方案选择

        • 读多写少:CopyOnWriteArrayList(内部使用写时复制机制)
        • 写多读少:Collections.synchronizedList(new ArrayList<>())+合理锁粒度
        • 相关问答FAQs

          Q1: 什么时候应该选择ArrayList而不是LinkedList?

          A: 当业务场景以随机访问为主时(如根据ID查询订单),ArrayList的O(1)时间复杂度优势明显;若主要进行频繁的插入/删除操作(如日志队列),则应选择LinkedList,实测数据显示,在百万级数据量下,ArrayList的随机访问速度比LinkedList快约3个数量级。

          Q2: 为什么遍历ArrayList时修改会抛出ConcurrentModificationException?

          A: 这是Java集合框架的快速失败机制(Fail-Fast)。ArrayList内部维护了一个modCount计数器,每次结构性修改(增删改)都会递增该值,迭代器的checkForComodification()方法会在每次next()操作前检查预期修改次数是否匹配实际修改次数,若检测到不一致(即遍历过程中发生了结构性修改),立即抛出异常,这种设计是为了及时发现并发修改问题,保证数据一致性,解决方案包括:①使用迭代器的remove()方法;②改用for循环倒序删除;③克隆新

0