目录

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

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
四谎真好看1 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程1 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t1 小时前
ZIP工具类
java·zip
lang201509281 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan2 小时前
第10章 Maven
java·maven
百锦再3 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说3 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多3 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再3 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父3 小时前
Spring—注解开发
java·后端·spring