List 集合是 Java 集合中最常用的集合,支持有序且可重复插入的数据集。存储功能类似于数组,根据插入顺序排序。

特点

  • 有序性: 根据插入顺序排序;
  • 可重复行: 可以重复插入相同的数据;
  • 索引支持:提供整数类型的索引,类似数组可以根据索引获取集合中的元素。

常见实现类

ArrayList

  • 底层基于 Object[] 实现的动态数组,自动扩容;
  • 非线程安全集合,多线程同时修改会提示ConcurrentModificationException 异常;
  • 插入数据需要移动元素,适合查询多,插入少的环境;
  • 默认初始容量为10,扩容为1.5倍。

LinkedList

  • 底层基于双向链表实现,每个元素存储了其直接前驱和后驱的指针,支持双向遍历;
  • 非线程安全集合;
  • 若执行插入操作,若直接插入头或尾部较为方便,若要在中间插入,则需要遍历查找插入位置然后修改前后驱存储信息;
  • 适用与频繁对其头尾进行插入操作,或不需要频繁访问的场景。

Vector

  • 所有方案都用 synchronized 修饰,已被 CopyOnWriteArrayList 替代;
  • 默认初始容量为10,扩容为2倍;
  • 线程安全的数据。

CopyOnWriteArrayList

  • 基于数组,但写操作会复制新数组,读操作访问旧数组;
  • 线程安全的,写操作加锁 ReentrantLock ,并通过复制数组操作实现读写分离;
  • 无固定扩容策略,每次写操作都会复制新数组,容量随元素增加自动扩容;
  • 使用与读多写少的并发场景。

常用方法

新增

boolean add(E e);//按顺序添加元素
void add(int index, E element);//添加元素到指定位置
boolean addAll(Collection<? extends E> c);//批量添加元素

获取元素

E get(int index);//根据索引获取指定位置元素

修改元素

E set(int index, E element);//修改指定位置的元素

删除元素

E remove(int index);//删除指定位置的元素
boolean remove(Object o);//删除与传入元素匹配的元素
boolean removeAll(Collection<?> c);//批量删除元素

查询信息

boolean contains(Object o);//查询元素是否存在
boolean containsAll(Collection<?> c);//批量查询元素是否存在
int indexOf(Object o);//查询元素在集合中的位置
int lastIndexOf(Object o);//查询元素在集合中最后一次出现的位置
boolean isEmpty();//查询集合是否为空
int size();//查询集合的长度

代码示例

public static void main(String[] args) {  
    List<String> list = new ArrayList<>();  
  
    /**  
     * 新增元素  
     */  
    list.add("张三");//按顺序添加元素  
    list.add(0, "王五");//添加元素到指定位置  
    ArrayList<String> all = new ArrayList<>();  
    all.add("李四");  
    all.add("JOJO");  
    list.addAll(all);//批量添加元素  
  
    System.out.println(list);  
  
    /**  
     * 获取元素  
     */  
    String s = list.get(0);//获取指定位置的元素  
    System.out.println(s);  
  
    /**  
     * 修改元素  
     */  
    list.set(0,"江南");//修改指定位置的元素  
    System.out.println(list);  
  
    /**  
     * 删除元素  
     */  
    list.remove(0);  
    System.out.println(list);  
    list.remove("JOJO");  
    System.out.println(list);  
    list.removeAll(all);//批量删除元素  
    System.out.println(list);  
  
    /**  
     * 查询元素  
     */  
    boolean b = list.contains("张三");//查询元素是否存在  
    System.out.println(b);  
    boolean b1 = list.containsAll(all);//批量查询元素是否存在  
    System.out.println(b1);  
    int i = list.indexOf("张三");//查询元素在集合中的位置  
    System.out.println(i);  
    int i1 = list.lastIndexOf("张三");//查询元素在集合中最后一次出现的位置  
    System.out.println(i1);  
    boolean b2 = list.isEmpty();//查询集合是否为空  
    System.out.println(b2);  
    int size = list.size();//查询集合的长度  
    System.out.println(size);  
}

注意

  1. 线程安全:若需线程安全的List,优先选CopyOnWriteArrayList(写时复制,读操作无锁,适合读多写少),而非Vector(全方法加锁,性能差)。
  2. 索引越界:使用get/set/remove时,索引需在[0, size()-1]范围内,否则抛出IndexOutOfBoundsException
  3. null支持:List允许null元素(如fruits.add(null)是合法的)。