java小白日记38(集合-List)

List接口基本介绍

List接口是collection接口的子接口

(1)List集合类中元素有序 (即添加顺序和取出顺序一致)、且可以重复

(2)List集合中的每个元素都有其对应的顺序索引,即支持索引

(3)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

(4)JDK API中List接口的实现类常用的有:ArrayList、LinkedList、Vector

List接口方法使用

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        // 添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        // 获取元素
        System.out.println("First element: " + list.get(0));

        // 修改元素
        list.set(1, "Blueberry");

        // 删除元素
        list.remove("Cherry");

        // 遍历列表
        for (String fruit : list) {
            System.out.println(fruit);
        }

        // 检查元素是否存在
        System.out.println("Contains Apple: " + list.contains("Apple"));

        // 列表大小
        System.out.println("List size: " + list.size());
    }
}

ArrayList的注意事项

(1)ArrayList可以加入null

(2)ArrayList是由数组来实现数据存储的

(3)ArrayList基本等同Vector,除了ArrayList是线程不安全的(执行效率高),在多线程情况下,不建议使用ArrayList

ArrayList的底层结构:

(1)ArrayList中维护了一个Object类型的数组elementDate

transient Object\[\] elementDate;//transient 表示短暂的,表示该属性不会被序列化

(2)当创建ArrayList对象时,如果使用的是无参构造器,则elementDate容量为0,第一次添加,则扩容elementDate为10,如需要再次扩容,则扩容的elementDate为1.5倍

(3)如果使用的是指定大小的构造器,则初始elementDate容量为指定大小,如果需要扩容,则直接扩容elementDate的1.5倍

java 复制代码
import java.util.Arrays;

public class ArrayList<E> {
    // 默认初始容量
    private static final int DEFAULT_CAPACITY = 10;

    // 空数组,用于无参构造器初始化
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 默认空数组,用于无参构造器初始化(延迟初始化)
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 存储元素的数组
    transient Object[] elementData;

    // 当前元素的数量
    private int size;

    // 最大数组容量(Integer.MAX_VALUE - 8)
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // 无参构造器
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // 初始化为默认空数组
    }

    // 有参构造器,指定初始容量
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity]; // 创建指定容量的数组
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA; // 使用空数组
        } else {
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); // 抛出异常
        }
    }

    // 添加元素方法
    public boolean add(E e) {
        ensureCapacityInternal(size + 1); // 确保容量足够
        elementData[size++] = e; // 添加元素到数组末尾
        return true;
    }

    // 确保内部容量足够
    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 如果是无参构造器创建的ArrayList,第一次添加元素时使用默认容量
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }

    // 显式确保容量足够
    private void ensureExplicitCapacity(int minCapacity) {
        if (minCapacity - elementData.length > 0) {
            grow(minCapacity); // 如果当前容量不足,则扩容
        }
    }

    // 扩容方法
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length; // 获取当前容量
        int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量 = 旧容量 * 1.5
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity; // 如果新容量小于所需容量,则使用所需容量
        }
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            newCapacity = hugeCapacity(minCapacity); // 处理超大容量
        }
        elementData = Arrays.copyOf(elementData, newCapacity); // 创建新数组并复制内容
    }

    // 处理超大容量
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) {
            throw new OutOfMemoryError(); // 如果minCapacity溢出,抛出OutOfMemoryError
        }
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }

    // 获取当前元素数量
    public int size() {
        return size;
    }

    // 获取当前数组容量(通过反射实现,仅用于测试)
    public int getCapacity() {
        return elementData.length;
    }
}

Vector底层结构:

(1)Vector底层也是一个对象数组,protected Object\[\] elementDate;

(2)Vector是线程同步的,即线程安全,Vector类的操作方法中带有synchronized

(3)在开发中,需要线程同步安全时,考虑使用Vector

Vector底层结构和ArrayList的比较

LinkedList的底层操作机制:

(1)LinkedList的底层维护了一个双向链表

(2)LinkedList中维护了两个属性first和last

ArrayList和LinkedList的比较

如何选择ArrayList和LinkedList:

(1)如果我们改查多,选择ArrayList

(2)如果增删多,选择LinkedList

(3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList

(4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用ArrayList,另一个模块使用LinkedList

相关推荐
xcl09251 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐3 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长3 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn3 小时前
Spring 注解使用详解
java·spring
一条小小yu3 小时前
Spring IoC的理解
java·后端·spring
落魄实习生4 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈4 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白5 小时前
核心功能(Service接口)
java·mybatis
乌暮6 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习