博客
关于我
List集合(源码学习)
阅读量:643 次
发布时间:2019-03-14

本文共 5507 字,大约阅读时间需要 18 分钟。

List集合详解:ArrayList、LinkedList、Vector与Stack

摘要

List集合是属于集合接口的一种特殊集合,其主要特点是支持有序、可重复以及通过索引进行快速元素操作。Java提供了三种主要的List实现类:ArrayList、LinkedList和Vector,除此之外,Stack作为Vector的子类也提供了一个典型的栈实现。本文将从ArrayList的详细实现原理入手,接着比较不同List实现类的优缺点,最后深入探讨Vector及Stack的应用场景及其实现细节。

List集合概述

List集合是集合接口中的一种特殊集合,其特点包括:

  • 有序:集合中的元素按照一定规则排列,支持通过索引快速访问。
  • 可重复:同一个元素可以多次存在于集合中。
  • 可null元素:List集合允许包含Null元素,这与集合的其他实现(如Set)不同。

List集合的核心特征体现在其支持默认的implemented methods,包括:

  • add方法:支持插入元素
  • remove方法:支持删除元素
  • contains方法:支持元素存在性查询
  • get方法:支持按索引查询元素
  • containsAll方法:支持查询多个元素的存在性
  • size方法:支持返回集合大小
  • isEmpty方法:支持判断集合是否为空
  • iterator方法:支持创建迭代器进行集合遍历

List集合类型比较:ArrayList详解

ArrayList基本特性

ArrayList是基于数组的动态容器,其实现基于一个动态大小的数组,因此其在随机访问(get方法)和元素遍历(iterator)方面操作极其高效。但在单个元素插入和删除操作时,由于需要进行数组的动态扩展或收缩,操作效率较低。

ArrayList初始化方式

ArrayList提供了三种主要的初始化方式:

  • 默认初始化:初始化时使用默认容量10,适合大多数场景。
  • public ArrayList() {
    elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    1. 指定容量:允许开发者根据需求初始化指定容量。
    2. public ArrayList(int initialCapacity) {
      if (initialCapacity > 0) {
      elementData = new Object[initialCapacity];
      } else if (initialCapacity == 0) {
      elementData = EMPTY_ELEMENT_DATA;
      } else {
      throw new IllegalArgumentException("Illegal capacity: " + initialCapacity);
      }
      }
      1. 从Collection复制:支持接收其他集合的元素进行初始化。
      2. public ArrayList(Collection c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
        if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
        elementData = EMPTY_ELEMENT_DATA;
        }
        }

        ArrayList的扩容机制

        ArrayList的动态扩容机制是维护一个扩容阈值的策略,以确保在元素添加时不会因为容量不足而导致内存溢出。具体来说:

      3. 默认扩容策略:当元素数量超过当前数组容量的1.5倍时会扩容。
      4. 双倍扩容:当新容量不足以满足当前插入需求时,将根据需求动态调整新容量。
      5. 特殊容量处理:如果容量超过了默认的Integer.MAX_VALUE - 8,则视为最大可能值。
      6. 异桩扩容:通过堆积式扩容以提升效率。
      7. 示例分析

        • 第一个元素加入时,数组大小为0,将通过扩容机制扩充至10。
        • 当需要添加第十一(11)个元素时,当前数组大小为10,满足容量的1.5倍(10*1.5=15),所以当需要加入第十一(11)个元素时,会扩容至20。

        ArrayList的基本操作

        ArrayList的核心操作方法包括:

        • add方法:负责元素的插入,默认实现通过数组的append操作。
        • remove方法:负责元素的删除,当删除元素时需要处理数组的连续性调整。
        • get方法:通过数组下标直接获取元素,实现随机访问。
        • ** iterator 方法**:提供一个迭代器,负责按顺序遍历集合中的所有元素。

        代码示例

        public class TestArrayList {
        public static void main(String[] args) {
        ArrayList
        list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        System.out.println("元素数量:" + list.size());
        for (String s : list) {
        System.out.println("元素:" + s);
        }
        }
        }

        LinkedList详解:基于链表的双向列表

        LinkedList特性

        LinkedList 的特点包括:

        • 双向链表结构:每个节点包含前驱和后继指针。
        • 增删快、查询慢:插入和删除操作平均时间复杂度为O(1),查询操作的平均复杂度为O(n)。
        • 绝对的线性数组表现:当List的元素数量较大时,List实现类的性能差异会变得更加明显。
        • 高内维度操作:在单线程环境下,LinkedList的性能优于ArrayList,但在多线程环境下,ArrayList的性能优势更为突出。

        代码示例

        public class TestLinkedList {
        public static void main(String[] args) {
        LinkedList
        list = new LinkedList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        System.out.println("元素数量:" + list.size());
        for(String s : list) {
        System.out.println("元素:" + s);
        }
        }
        }

        Vector的线程安全实现

        Vector集合的特点包括:

        • 线程安全:通过对所有公用操作的同步保护,确保多线程环境下的数据一致性。
        • 同步机制:核心方法(如add、remove、contains等)都带有 synchronized 关键字。
        • 同步策略:所有修改集合元件的操作都需要获得集合的内部锁,这保证了在多线程环境下集合的安全使用。

        并发测试示例

        import java.util.Vector;
        import java.util.concurrent.CountDownLatch;
        public class ConcurrentVectorTest {
        public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(2);
        Vector
        vector = new Vector<>();
        MyThread myThread1 = new MyThread(countDownLatch, vector, "abc");
        MyThread myThread2 = new MyThread(countDownLatch, vector, "abc");
        myThread1.start();
        myThread2.start();
        countDownLatch.await();
        System.out.println("集合大小:" + vector.size());
        for(int i = 0; i < vector.size(); i++) {
        System.out.println("索引:" + i + " 元素:" + vector.get(i));
        }
        }
        static class MyThread extends Thread {
        private CountDownLatch countDownLatch;
        private Vector
        vector;
        private String element;
        public MyThread(CountDownLatch countDownLatch, Vector
        vector, String element) {
        this.countDownLatch = countDownLatch;
        this.vector = vector;
        this.element = element;
        }
        @Override
        public void run() {
        try {
        if (!vector.contains(element)) {
        Thread.sleep(1000);
        vector.add(element);
        }
        } catch (InterruptedException e) {
        e.printStackTrace();
        } finally {
        countDownLatch.countDown();
        }
        }
        }
        }

        Stack的实现与应用

        Stack类是Vector的一个内部扩展类,提供一个典型的先进后出的栈操作。Stack的主要操作包括:

        • push:将元素压入栈顶。
        • pop:将栈顶元素弹出。
        • peek:查看栈顶元素。
        • search:查找栈中的元素。

        Stack的实现主要依赖于内部维护的一个动态数组:

        public class Stack
        extends Vector
        {
        public Stack() {
        super();
        }
        public boolean push(E item) {
        return super.addElement(item);
        }
        @Override
        public E pop() {
        return super.removeElementAt(size());
        }
        @Override
        public E peek() {
        return super.elementAt(size());
        }
        }

        总结

        List集合在Java中扮演着关键的数据结构角色,其主要应用场景包括:

        • 数据存储与管理:用于有序存储大量数据。
        • 广度优先搜索(BFS):在图结构中,List集合可以用作队列,实现广度优先搜索。
        • 中间结果缓存:用于临时存储中间处理的数据。

        选择List集合的具体实现类取决于具体需求:

        • ArrayList:适合对随机访问和数据迭代要求较高的场景。
        • LinkedList:适合对插入、删除操作要求低,且不介意查询效率较高的场景。
        • Vector:适合线程安全要求严格,且需要随机访问的场景。
        • Stack:适合模拟栈结构,典型场景包括括号匹配、调用栈等。

        通过合理选择List集合的实现类,可以在不同的场景下实现最优的性能表现。

    转载地址:http://nqqoz.baihongyu.com/

    你可能感兴趣的文章
    np.arange()和np.linspace()绘制logistic回归图像时得到不同的结果?
    查看>>
    np.power的使用
    查看>>
    NPM 2FA双重认证的设置方法
    查看>>
    npm build报错Cannot find module ‘webpack/lib/rules/BasicEffectRulePlugin‘解决方法
    查看>>
    npm build报错Cannot find module ‘webpack‘解决方法
    查看>>
    npm ERR! ERESOLVE could not resolve报错
    查看>>
    npm ERR! fatal: unable to connect to github.com:
    查看>>
    npm ERR! Unexpected end of JSON input while parsing near '...on":"0.10.3","direc to'
    查看>>
    npm ERR! Unexpected end of JSON input while parsing near ‘...“:“^1.2.0“,“vue-html-‘ npm ERR! A comp
    查看>>
    npm error Missing script: “server“npm errornpm error Did you mean this?npm error npm run serve
    查看>>
    npm error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”。要解决此问题,1) 安装
    查看>>
    npm install CERT_HAS_EXPIRED解决方法
    查看>>
    npm install digital envelope routines::unsupported解决方法
    查看>>
    npm install 卡着不动的解决方法
    查看>>
    npm install 报错 EEXIST File exists 的解决方法
    查看>>
    npm install 报错 ERR_SOCKET_TIMEOUT 的解决方法
    查看>>
    npm install 报错 Failed to connect to github.com port 443 的解决方法
    查看>>
    npm install 报错 fatal: unable to connect to github.com 的解决方法
    查看>>
    npm install 报错 no such file or directory 的解决方法
    查看>>
    npm install 权限问题
    查看>>