Java集合框架:List集合详解与应用

三、List系列集合

前面我们已经把Collection通用的功能学习完了,接下来我们学习Collection下面的一个子体系List集合。如下图所示:

3.1 List集合的常用方法

List集合是索引的,所以多了一些有索引操作的方法,如下图所示:

接下来,我们用代码演示一下这几个方法的效果

复制代码
public class ListTest1 {
    public static void main(String[] args) {
        // 创建一个ArrayList集合对象(有序、有索引、可以重复)
        List<String> list = new ArrayList<>();
        list.add("蜘蛛精");
        list.add("至尊宝");
        list.add("至尊宝");
        list.add("牛夫人");
        System.out.println(list); // [蜘蛛精, 至尊宝, 至尊宝, 牛夫人]
​
        // 在某个索引位置插入元素
        list.add(2, "紫霞仙子");
        System.out.println(list); // [蜘蛛精, 至尊宝, 紫霞仙子, 至尊宝, 牛夫人]
​
        // 根据索引删除元素, 返回被删除的元素
        System.out.println(list.remove(2)); // 紫霞仙子
        System.out.println(list);// [蜘蛛精, 至尊宝, 至尊宝, 牛夫人]
​
        // 返回集合中指定位置的元素
        System.out.println(list.get(3));
​
        // 修改索引位置处的元素,修改后,会返回原数据
        System.out.println(list.set(3, "牛魔王")); // 牛夫人
        System.out.println(list); // [蜘蛛精, 至尊宝, 至尊宝, 牛魔王]
    }
}

3.2 List集合的遍历方式

List集合相比于前面的Collection多了一种可以通过索引遍历的方式,所以List集合遍历方式一共有四种:

  • 普通for循环(只因为List有索引)

  • 迭代器

  • 增强for

  • Lambda表达式

复制代码
public class ListTest2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("蜘蛛精");
        list.add("至尊宝");
        list.add("糖宝宝");
​
        // 1.普通for循环
        for(int i = 0; i< list.size(); i++){
            //i = 0, 1, 2
            String e = list.get(i);
            System.out.println(e);
        }
​
        System.out.println("--------------");
​
        // 2.增强for遍历
        for(String s : list){
            System.out.println(s);
        }
​
        System.out.println("--------------");
​
        // 3.迭代器遍历
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
​
        System.out.println("--------------");
​
        // 4.lambda表达式遍历
        list.forEach(s -> System.out.println(s));
    }
}

3.3 ArrayList底层的原理(面试题)

为了让同学们更加透彻的理解ArrayList集合,接下来,学习一下ArrayList集合的底层原理。

ArrayList集合底层(存储、组织数据的方式)是基于数组结构实现的,也就是说当你往集合容器中存储元素时,底层本质上是往数组中存储元素。 特点如下:

我们知道数组的长度是固定的,但是集合的长度是可变的,这是怎么做到的呢?

集合的底层原理如下:

数组扩容,并不是在原数组上扩容(原数组是不可以扩容的),底层是创建一个新数组,然后把原数组中的元素全部复制到新数组中去。

以上就是ArrayList底层的原理。

3.4 ArrayList的应用场景

复制代码
应用场景:
    1、ArrayList适合: 根据索引查询数据,比如根据随机索引取数据(高效)! 或者数据量不是很大时!
    2、ArrayList不适合: 数据量大的,同时又要频繁的进行增删操作!

复制代码
总结:
1、List系列集合的特点是什么?
    ArrayList、LinekdList :有序,可重复,有索引。
​
2、ArrayList集合的底层是基于什么实现的, 有什么特点呢?
    数组
    特点:
        查询快, 增删慢
    
3、ArrayList集合适合什么业务场景?不适合什么业务场景?
    ArrayList适合: 根据索引查询数据,比如根据随机索引取数据(高效)! 或者数据量不是很大时!
    ArrayList不适合: 数据量大的,同时又要频繁的进行增删操作!

3.5 LinkedList底层原理

学习完ArrayList底层原理之后,接下来我们看一下LinkedList集合的底层原理。

LinkedList底层是链表结构,基于双链表实现的。

链表结构是由一个一个的节点组成,一个节点由数据值、下一个元素的地址组成。如下图所示:

假如,现在要在B节点和D节点中间插入一个元素,只需要把B节点指向D节点的地址断掉,重新指向新的节点地址就可以了。如下图所示:

假如,现在想要把D节点删除,只需要让C节点指向E节点的地址,然后把D节点指向E节点的地址断掉。此时D节点就会变成垃圾,会被垃圾回收器清理掉。

上面的链表是单向链表,它的方向是从头节点指向尾节点的,只能从左往右查找元素,这样查询效率比较慢;还有一种链表叫做双向链表,不光可以从左往右找,还可以从右往左找。如下图所示:

LinkedList集合是基于双向链表实现了,为什么它会对首尾元素进行增删改查的速度是极快的,因为双向链表是有头结点地址和尾结点地址, 通过头结点地址和尾结点地址可以快速的找到第一个元素

和最后一个元素,那么在头和尾节点进行增删速度肯定是极快的,比如在尾结点后加一个元素,让尾结点指向新加的元素,那么新加的元素就是尾结点,头结点同理可知,如果删除尾结点,尾结点一旦删除倒数第二个就是尾结点,所以说首尾元素进行增删改查的速度是极快的,但是对中间的数据还是需要找到对应节点位置才可以操作。

所以相对于ArrayList新增了一些可以针对头尾进行操作的方法,如下图示所示:

3.6 LinkedList集合的应用场景

刚才我们学习了LinkedList集合,那么LinkedList集合有什么用呢?可以用它来设计栈结构、队列结构。

  • 我们先来认识一下队列结构,队列结构你可以认为是一个上端开口就是入队,下端也开口的管子的形状就是出队。元素从上端入队列,从下端出队列。所以队列的特点就是先进先出,后进后出

入队列可以调用LinkedList集合的addLast方法,出队列可以调用removeFirst()方法.

复制代码
public class LinkedListTest1 {
    public static void main(String[] args) {
        // 创建一个队列:先进先出、后进后出
        LinkedList<String> queue = new LinkedList<>();
​
        // 入对列
        queue.addLast("第1号人");
        queue.addLast("第2号人");
        queue.addLast("第3号人");
        queue.addLast("第4号人");
        System.out.println(queue);
​
        // 出队列
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
​
        System.out.println(queue);
    }
}
  • 接下来,我们再用LinkedList集合来模拟一下栈结构的效果。还是先来认识一下栈结构长什么样。栈结构可以看做是一个上端开头,下端闭口的水杯的形状。

    元素永远是上端进,也从上端出,先进入的元素会压在最底下,所以栈结构的特点是先进后出,后进先出

有没有感觉栈结构很像,手枪的子弹夹呀!!第一个压进入的子弹在最底下,最后一个才能打出来,最后一个压进入的子弹在最顶上,第一个打出来。

接着,我们就用LinkedList来模拟下栈结构,代码如下:

复制代码
public class LinkedListTest2 {
    public static void main(String[] args) {
        //创建一个栈对象
        LinkedList<String> stack = new LinkedList<>();
​
        // addFirst()
        /*stack.addFirst("第1颗子弹");
        stack.addFirst("第2颗子弹");
        stack.addFirst("第3颗子弹");
        stack.addFirst("第4颗子弹");*/
​
        // 压栈(push) 等价于 addFirst()
        stack.push("第1颗子弹");
        stack.push("第2颗子弹");
        stack.push("第3颗子弹");
        stack.push("第4颗子弹");
        System.out.println(stack); //[第4颗子弹, 第3颗子弹, 第2颗子弹,第1颗子弹]
​
        // removeFirst()
        /*System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());*/
​
        // 弹栈(pop) 等价于 removeFirst()
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
​
        //弹栈完了,集合中就没有元素了
        System.out.println(stack); //[]
    }
}
复制代码
总结:
LinkedList集合的底层原理
    基于双链表实现的。
    特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的。
相关推荐
fan_music1 小时前
C语言如何实现C++的类
开发语言·c++
极客先躯1 小时前
高级java每日一道面试题-2025年12月08日-实战篇[Docker]-如何为 Docker 配置代理?如何为容器配置代理?
java·docker·代理配置的双层架构·docker 守护进程配置代理·为容器配置代理·构建时环境变量·运行时注入环境变量
毋语天1 小时前
Python 常用内置模块详解:日志、随机数、时间、OS 与 JSON
开发语言·python
一个人旅程~1 小时前
如何永久关闭bitlocker并防止出现更新后被强制加密?
linux·windows·经验分享·电脑
csdn2015_1 小时前
java springboot 文件导入,判断第一列的值是否有重复
java·windows·spring boot
扬帆破浪1 小时前
免费开源AI软件.桌面单机版,可移动的AI知识库,察元 AI桌面版:本地离线知识库的妥协与收益 老电脑跑察元AI的可行边界
人工智能·windows·开源·电脑·知识图谱
右耳朵猫AI1 小时前
Python技术周刊 2026年第14周
开发语言·python·okhttp
叼烟扛炮1 小时前
C++ 知识点22 函数模板
开发语言·c++·算法·函数模版
~|Bernard|1 小时前
四,go语言中GMP调度模型
java·前端·golang