【Java】LinkedList 集合

LinkedList集合特点

LinkedList 底层基于双向链表实现增删 效率非常高,查询效率非常低。


LinkedList源码解读分析

  1. LinkedList 是双向链表实现的 List
  2. LinkedList 是非线程安全的(线程是不安全的)
  3. LinkedList 元素允许为null,允许重复元素
  4. LinkedList 是基于链表是实现的,因此插入删除效率高(如果根据下标增删 效率还是非常低的),查询效率低
  5. LinkedList 是基于链表实现的,因此不存在容量不足的问题,所以没有扩容的方法
  6. LinkedList 还是实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用


示例代码:

java">package com.collection.Demo08;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;


public class Test01 {
    public static void main(String[] args) {
        /**
         * LinkedList 底层基于链表实现 增删 效率非常高 查询效率是非常低
         */
        List<String> linkedList = new LinkedList<>();
        linkedList.add("mayikt1");
        linkedList.add("mayikt2");
        linkedList.add("mayikt3");
        linkedList.get(0);
        /**
         * LinkedList get()底层是如何实现的呢?
         * 底层基于双向链表实现
         */
        System.out.println(linkedList.size());
        Iterator<String> iterator = linkedList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("===删除之后===");
        linkedList.remove(1);
        Iterator<String> iterator2 = linkedList.iterator();
        while (iterator2.hasNext()){
            System.out.println(iterator2.next());
        }
    }
}
java">package com.collection.Demo08;

import java.util.LinkedList;

public class Test02 {
    public static void main(String[] args) {
        LinkedList<String> strings = new LinkedList<>();
        strings.add("mayikt01");
        strings.add("mayikt02");
        strings.add("mayikt03");
        strings.remove(0);
        System.out.println(strings.get(0));//mayikt01
        System.out.println(strings.getFirst());//mayikt01
        System.out.println(strings.getLast());//mayikt03
    }
}

 手写LinkedList集合

java">package com.collection.Demo08;

/**
 * LinkedList底层是基于链表实现
 * 手写LinkedList集合
 */

public class MayiktLinkedList<E> {
    private Node<E> first;//第一个节点
    private Node<E> last; //最后一个节点
    int size = 0; //LinkedList存放的元素个数

    private static class Node<E> {
        private E item;//当前节点的值
        private Node<E> prev;//上一个节点
        private Node<E> next;//下一个节点
//        transient Node<E> next;// transient表示next节点不能够被序列化的

        /**
         * @param prev 当前节点的上一个节点
         * @param item 当前节点的值
         * @param next 当前节点的下一个节点
         */
        public Node(Node<E> prev, E item, Node<E> next) {
            this.item = item;
            this.prev = prev;
            this.next = next;
        }
    }

    public void add(E e) {
        //add()创建一个新的node节点时,新的node节点的上一个节点是还未新增时的last尾节点
        Node l = last;//获取当前链表中最后一个节点
        //创建一个新的node节点
        //newNode节点的上一个节点,就是当前链表中的最后一个节点
        Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null) {
            //如果在链表中没有最后一个节点的话——链表为空
            first = newNode;
        } else {
            l.next = newNode;
        }
        size++;
    }

    /**
     * 根据index 查询 链表中对应的node节点
     * 对半查找
     */
    Node<E> node(int index) {
        if (index < size >> 1) { //size >>1 =>size/2
            //查询链表中间值的左边
            Node<E> f = first;
            for (int i = 0; i < index; i++) {
                f = f.next;
            }
            return f;
        } else {
            //查询链表中间值的右边
            Node<E> l = last;
            for (int i = size - 1; i > index; i--) {
                l = l.prev;
            }
            return l;
        }
    }

    public E get(int index) {
        //下标如果越界的话 需要抛出异常
        return node(index).item;
    }

    //根据下标查询
    public E remove(int index) {
        return unlink(node(index));
    }

    private E unlink(Node<E> node) {
        //1.根据index 查询对应的node节点,时间复杂度为O(n)
        //2.删除链表效率非常高,比arrayList效率高,因为arrayList需要移动数组,而链表只需修改prev,next的指向问题
        //获取删除的node节点 上一个和下一个node节点
        final E element = node.item;//获取删除节点元素值
        Node<E> prev = node.prev;//删除节点的上一个节点
        Node<E> next = node.next;//删除节点的下一个节点
        //如果删除的节点 上一个节点为空
        if (prev == null) { //删除的该节点是头节点
            first = next;
        } else {
            prev.next = next;
            node.prev = null;//改为null,是为了通知GC 回收
        }
        if (next == null) {//删除的该节点是尾节点
            last = prev;
        } else {
            next.prev = prev;
            node.next = null;
        }
        node.item = null;//改为null,是为了通知GC 回收
        size--;
        return element;
    }

    public static void main(String[] args) {
        MayiktLinkedList<String> stringMayiktLinkedList = new MayiktLinkedList<>();
        stringMayiktLinkedList.add("mayikt01");
        stringMayiktLinkedList.add("mayikt02");
        stringMayiktLinkedList.add("mayikt03");
        stringMayiktLinkedList.add("mayikt04");
        stringMayiktLinkedList.remove(1);
        System.out.println(stringMayiktLinkedList.get(0));
        System.out.println(stringMayiktLinkedList.get(1));
//        System.out.println(stringMayiktLinkedList.get(2));
//        System.out.println(stringMayiktLinkedList.get(3));
    }
}

下一篇文章:HashMap集合


http://www.niftyadmin.cn/n/5134153.html

相关文章

Python基础入门例程25-NP25 有序的列表(列表)

最近的博文&#xff1a; Python基础入门例程24-NP24 淘汰排名最后的学生&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程23-NP23 删除好友&#xff08;列表&#xff09;-CSDN博客 Python基础入门例程22-NP22 删除简历&#xff08;列表&#xff09;-CSDN博客 目录 最…

JVM第二十三讲:Java动态调试技术原理

Java动态调试技术原理 本文是JVM第二十三讲&#xff0c;Java动态调试技术原理。转载自 美团技术团队胡健的Java 动态调试技术原理及实践&#xff0c;通过学习java agent方式进行动态调试&#xff0c;了解目前很多大厂开源的一些基于此的调试工具 (例如来自阿里开源的Arthas)。 …

IOC课程整理-15 Spring 类型转换

1. Spring 类型转换的实现 2. 使用场景 3. 基于 JavaBeans 接口的类型转换 4. Spring 內建 PropertyEditor 扩展 5. 自定义 PropertyEditor 扩展 6. Spring PropertyEditor 的设计缺陷 7. Spring 3 通用类型转换接口 8. Spring 內建类型转换器 9. Converter 接口的局限性 10. G…

VBA宏查找替换目录下所有Word文档中指定字符串

原来搞质量管理&#xff0c;要替换质量文件里面所有特定名称或者某一错误时&#xff0c;需要逐一打开所有文件&#xff0c;非常麻烦&#xff0c;所以写了个VBA程序。过了这么多年&#xff0c;突然又要做同样的事情&#xff0c;发现新版本Word不支持其中的Application.FileSearc…

ImportError: DLL load failed while importing _pyopenvino: 找不到指定的程序

ImportError: DLL load failed while importing _pyopenvino: 找不到指定的程序 完全按照官方的pip安装方式&#xff0c;但是报错 解决方法&#xff1a; 下载下面压缩包 官网下载链接 解压到 运行程序之前 完成&#xff01;&#xff01;&#xff01; 测试 python -c &quo…

前端移动web高级详细解析三

模拟移动设备&#xff0c;方便查看页面效果 屏幕分辨率 分类&#xff1a; 物理分辨率&#xff1a;硬件分辨率&#xff08;出厂设置&#xff09; 逻辑分辨率&#xff1a;软件 / 驱动设置 结论&#xff1a;制作网页参考 逻辑分辨率 视口 作用&#xff1a;显示 HTML 网页的区…

虚拟机Ubuntu下运行vue-element-admin项目

一.环境搭建 1.安装nodejs sudo apt install nodejs 安装完成后&#xff0c;查看对应的版本号 nodejs -v没有问题&#xff0c;会输出对应版本号&#xff0c;我这里是10.19.0 v10.19.0 2.安装npm sudo apt install npm安装完成查看对应的版本号&#xff0c;确认OK npm -…

MyBatis-Plus 与 Druid 结合 Dynamic-datasource 实现多数据源操作数据库

MyBatis-Plus 官网&#xff1a;https://baomidou.com/ MyBatis-Plus 官方文档&#xff1a;https://baomidou.com/pages/24112f/ dynamic-datasource 文档&#xff08;付费&#xff09;&#xff1a;https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611 创建数据库…