Java LinkedList源码分析

LinkedList继承关系

LinkedList

LinkedList概述

  • LinkedList底层是双向链表,不需要开辟连续的内存空间,可以存放在任意地方,每个数据内部维持链表的头节点和尾节点。
  • Node是LinkedList的一个静态内部类,是LinkedList的核心,内部维护具体的值和上下节点的关系。
  • 对比ArrayList增删效率高,查询效率低,线程不安全。

LinkedList源码分析

属性
//集合大小
transient int size = 0;
//指向头节点
transient Node<E> first;
//指向尾节点
transient Node<E> last;
构造函数
//无参构造函数
public LinkedList() {
}

//传入一个集合的构造函数
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}
静态内部类Node
private static class Node<E> {
    //具体的值
    E item;
    //下一个节点
    Node<E> next;
    //上一个节点
    Node<E> prev;
	//构造函数
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
getFirst()
//获取头节点的值,头节点为null抛出异常
public E getFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}
peekFirst()
//获取头节点,头节点为null时返回null
public E peekFirst() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}
getLast()
//获取尾节点的值
public E getLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return l.item;
}
peekLast()
//获取尾节点的值,尾节点为null时返回null
public E peekLast() {
    final Node<E> l = last;
    return (l == null) ? null : l.item;
}
removeFirst()
//删除头节点,并返回头节点的值,头节点为null时抛出异常
public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    //删除头节点
    return unlinkFirst(f);
}

//删除头节点
private E unlinkFirst(Node<E> f) {
	//获取头节点的值
    final E element = f.item;
    //获取头节点的下一个节点
    final Node<E> next = f.next;
    //将头节点的值和下一个节点设为null
    f.item = null;
    f.next = null; // help GC
    //将头节点指向下一个节点
    first = next;
    if (next == null)
        //如果下一个节点为null,尾节点设为null
        last = null;
    else
        //如果下一个节点不为null,将下一个节点的上一个节点设为null
        next.prev = null;
    //集合大小减1
    size--;
    //修改计数加1
    modCount++;
    //返回原头节点的值
    return element;
}
pollFirst()
//删除头节点,并返回头节点的值,头节点为null时返回null
public E pollFirst() {
    final Node<E> f = first;
    return (f == null) ? null : unlinkFirst(f);
}

removeLast()
//删除尾节点,并返回尾节点的值,尾节点为null时抛出异常
public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    //删除尾节点
    return unlinkLast(l);
}

//删除尾节点
private E unlinkLast(Node<E> l) {
    //获取尾节点的值
    final E element = l.item;
    //获取尾节点的上一个节点
    final Node<E> prev = l.prev;
    //将头节点的值和上一个节点的设为null
    l.item = null;
    l.prev = null; // help GC
    //将尾节点指向上一个节点
    last = prev;
    if (prev == null)
        //如果上一个节点为null,头节点设为null
        first = null;
    else
        //如果上一个节点不为null,将上一个节点的下节点设为null
        prev.next = null;
    //集合大小减1
    size--;
    //修改计数加1
    modCount++;
    //返回原尾节点的值
    return element;
}

pollLast()
//删除尾节点,并返回尾节点的值,尾节点为null时返回null
public E pollLast() {
    final Node<E> l = last;
    return (l == null) ? null : unlinkLast(l);
}

addFirst()
//添加头节点
public void addFirst(E e) {
    //添加头节点
    linkFirst(e);
}

linkFirst()
//添加头节点
private void linkFirst(E e) {
    //获取头节点的副本
    final Node<E> f = first;
    //创建新的头节点
    final Node<E> newNode = new Node<>(null, e, f);
    //头节点指向新节点
    first = newNode;
    if (f == null)
        //如果原头节点为null,将尾节点指向新节点
        last = newNode;
    else
        //如果原头节点不为null,将原头节点的上一个节点指向新节点
        f.prev = newNode;
    //集合大小加1
    size++;
    //修改计数加1
    modCount++;
}

addLast()
//添加尾节点
public void addLast(E e) {
    //添加尾节点
    linkLast(e);
}

linkLast()
//添加尾节点
void linkLast(E e) {
    //获取尾节点的副本
    final Node<E> l = last;
    //创建新的尾节点
    final Node<E> newNode = new Node<>(l, e, null);
    //尾节点指向新节点
    last = newNode;
    if (l == null)
        //如果尾节点为null,头节点指向新节点
        first = newNode;
    else
        //如果尾节点不为null,原尾节点的下一个节点指向新节点
        l.next = newNode;
    //集合大小加1
    size++;
    //修改计数加1
    modCount++;
}

add()
//在集合末尾添加一个元素
public boolean add(E e) {
    linkLast(e);
    return true;
}

//在指定位置添加一个元素
public void add(int index, E element) {
    //检查下标
    checkPositionIndex(index);
    if (index == size)
        //若下标等于size,直接添加尾节点
        linkLast(element);
    else
        //在指定位置添加节点
        linkBefore(element, node(index));
}

linkBefore()
//在指定节点前添加元素
void linkBefore(E e, Node<E> succ) {
    //获取指定节点的上一个节点
    final Node<E> pred = succ.prev;
    //创建新节点
    final Node<E> newNode = new Node<>(pred, e, succ);
    //指定节点的上一个节点指向新节点
    succ.prev = newNode;
    if (pred == null)
        //若指定节点的上一个节点为null,头节点指向新节点
        first = newNode;
    else
        //若指定节点的上一个节点不为null,则指定节点的下一个节点指向新节点
        pred.next = newNode;
    //集合大小加1
    size++;
    //修改计数加1
    modCount++;
}

remove()
//删除第一个元素
public E remove() {
    return removeFirst();
}

//删除指定下标的元素
public E remove(int index) {
    checkElementIndex(index);
    return unlink(node(index));
}

//删除指定值的元素
public boolean remove(Object o) {
    if (o == null) {
        //若该对象为null,使用==比较
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        //若该对象不为null,使用equals比较
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

unlink()
//删除指定元素,并返回值
E unlink(Node<E> x) {
    //获取该元素的值
    final E element = x.item;
    //获取该元素的下一个节点
    final Node<E> next = x.next;
    //获取该元素的上一个节点
    final Node<E> prev = x.prev;

    if (prev == null) {
        //上节点为null,说明该元素是头节点
        //头节点指向下一个节点
        first = next;
    } else {
        //上节点的下节点指向下一个节点
        prev.next = next;
        //指定元素的上节点设为null
        x.prev = null;
    }

    if (next == null) {
        //下节点为null,说明该元素是尾节点
        last = prev;
    } else {
        //下节点的上一个节点指向上节点
        next.prev = prev;
        //该元素的下节点设为null
        x.next = null;
    }

    //该元素的值设为null
    x.item = null;
    //集合大小减1
    size--;
    //修改计数加1
    modCount++;
    //返回该元素的值
    return element;
}
addAll()
//在末尾添加集合元素
public boolean addAll(Collection<? extends E> c) {
    return addAll(size, c);
}

//在指定位置添加集合元素
public boolean addAll(int index, Collection<? extends E> c) {
    //检查下标
    checkPositionIndex(index);

    //集合转数组
    Object[] a = c.toArray();
    //获取数组长度
    int numNew = a.length;

    if (numNew == 0)
        return false;

    //pred表示添加位置的前一个节点
    //succ表示添加位置的节点
    Node<E> pred, succ;
    
    if (index == size) {
        //若index等于size,说明在尾部添加
        //succ设为null,pred指向原尾元素
        succ = null;
        pred = last;
    } else {
        //sucss指向当前元素,pred执行当前元素的上节点
        succ = node(index);
        pred = succ.prev;
    }

    //遍历数组
    for (Object o : a) {
        E e = (E) o;
        //创建新节点
        Node<E> newNode = new Node<>(pred, e, null);
        if (pred == null)
            //若上一个节点为null,说明在下标为首节点的的位置,则头节点指向新节点
            first = newNode;
        else
            //上一个节点的下节点指向新节点
            pred.next = newNode;
        //pred指向下一个新节点
        pred = newNode;
    }

    //循环结束后
    if (succ == null) {
        //若succ为null,说明最后的节点是尾节点
        last = pred;
    } else {
        //最后新建节点的下节点指向succ
        pred.next = succ;
        //succ的上节点指向最后新建节点
        succ.prev = pred;
    }

    //集合数量加numNew
    size += numNew;
    //修改计数加1
    modCount++;
    return true;
}
node()
//获取指定位置的元素
Node<E> node(int index) {
    if (index < (size >> 1)) {
        //指定位置小于总大小的一半,从头节点开始遍历
        //获取头节点
        Node<E> x = first;
        //遍历到指定index
        for (int i = 0; i < index; i++)
            x = x.next;
        //返回元素
        return x;
    } else {
        //指定位置大于总大小的一半,从尾节点开始遍历
        //获取尾节点
        Node<E> x = last;
        //遍历到指定index
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        //返回元素
        return x;
    }
}
clear()
//清空集合
public void clear() {
    //遍历所有元素
    for (Node<E> x = first; x != null; ) {
        //保存下一个节点的副本
        //将遍历到的元的值、上节点、下节点设为null
        Node<E> next = x.next;
        x.item = null;
        x.next = null;
        x.prev = null;
        x = next;
    }
    //将头节点和尾节点设为null
    first = last = null;
    //集合大小设为0
    size = 0;
    //修改计数加1
    modCount++;
}

get()
//获取指定下标的元素
public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

set()
//设置指定下标位置的值,并返回旧值
public E set(int index, E element) {
    checkElementIndex(index);
    Node<E> x = node(index);
    E oldVal = x.item;
    x.item = element;
    return oldVal;
}

clone()
//克隆
//LinkedList的clone属于浅拷贝,只拷贝对象的引用
public Object clone() {
    //生产新的集合对象
    LinkedList<E> clone = superClone();
    //初始化状态
    clone.first = clone.last = null;
    clone.size = 0;
    clone.modCount = 0;

    //遍历原集合,将元素添加如新集合中
    for (Node<E> x = first; x != null; x = x.next)
        clone.add(x.item);

    return clone;
}


toArray()
//集合转数组
public Object[] toArray() {
    //创建新数组
    Object[] result = new Object[size];
    int i = 0;
    //遍历集合,并向数组添加元素
    for (Node<E> x = first; x != null; x = x.next)
        result[i++] = x.item;
    return result;
}

//将列表转为指定数组
public <T> T[] toArray(T[] a) {
    //数组的长度小于集合的size,重新构建数组的长度
    if (a.length < size)
        a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
    int i = 0;
    Object[] result = a;

    //遍历集合,对数组赋值
    for (Node<E> x = first; x != null; x = x.next)
        result[i++] = x.item;

    //若数组的长度大于size,在下标为size的位置设为null
    if (a.length > size)
        a[size] = null;

    return a;
}


contains()
//是否包含该对象
public boolean contains(Object o) {
    return indexOf(o) != -1;
}


indexOf()
//获取该对象的下标
public int indexOf(Object o) {
    int index = 0;
    if (o == null) {
        //该对象为null,使用==比较
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null)
                return index;
            index++;
        }
    } else {
        //该对象不为null,用equals比较
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item))
                return index;
            index++;
        }
    }
    //不存在则返回-1
    return -1;
}


size()
//获取集合大小
public int size() {
    return size;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JetLinks开源物联网平台基于Java8、Spring Boot 2.x、WebFlux、Netty、Vert.x、Reactor等开发,是一个开箱即用,可二次开发的企业级物联网基础平台。平台实现了物联网相关的众多基础功能,能帮助你快速建立物联网相关业务系统。 JetLinks开源物联网平台核心特性: 支持统一物模型管理,多种设备,多种厂家,统一管理。 统一设备连接管理,多协议适配(TCP、MQTT、UDP、CoAP、HTTP等),屏蔽网络编程复杂性,灵活接入不同厂家不同协议的设备。 灵活的规则引擎,设备告警,消息通知,数据转发。可基于SQL进行复杂的数据处理逻辑。 地理位置:统一管理地理位置信息,支持区域搜索。 数据可视化:实现拖拽配置数据图表,设备组态等。 JetLinks开源物联网平台技术栈: Spring Boot 2.2.x Spring WebFlux 响应式Web支持 R2DBC 响应式关系型数据库驱动 Project Reactor 响应式编程框架 Netty、Vert.x 高性能网络编程框架 ElasticSearch 全文检索,日志,时序数据存储 PostgreSQL 业务功能数据管理 hsweb framework 4 业务功能基础框架     JetLinks开源物联网平台 更新日志: v1.9 1、增加设备独立物模型支持,可给单独的设备配置物模型. 2、基本实现GB28181国标视频设备接入,支持直播,云台控制,级联操作.(选配模块) 3、RabbitMQ增加routeKey配置,可在配置文件中指定device.message.writer.rabbitmq.consumer-route-key和device.message.writer.rabbitmq.producer-route-key.(Pro) 4、当设置了device.message.writer.rabbitmq.consumer=false时,不创建MQ消费者.(Pro) 5、设备支持独立物模型,可单独配置设备的物模型. 6、适配tdengine 2.0.16.0,优化sql长度策略. (pro) 7、优化规则引擎编辑器,实现组件模块化动态加载.(Pro) 8、修复启动服务时,如果某个产品物模型发布失败,导致后面的产品终止发布的问题. 9、增加ignoreLatest消息头,message.addHeader("ignoreLatest",true) 忽略记录最新数据到数据库. 10、修复租户下操作设备告警提示无权限.(Pro) 11、优化租户在解绑成员时,同时解绑成员的资产信息.(Pro) 12、优化子设备消息回复处理 13、物模型属性增加存储方式功能,可配置部分属性不存储. 14、增加虚拟属性功能,可通过规则来计算出虚拟属性值.(Pro) 15、增加租户成员绑定(TenantMemberBindEvent),解绑(TenantMemberUnBindEvent)事件.可通过spring-event订阅处理此事件.(Pro) 16、优化子设备状态检查,当检查子设备状态时,将会尝试发送ChildDeviceMessage<DeviceStateCheckMessage>给网关,处理后返回ChildDeviceMessageReply<DeviceStateCheckMessageReply>. 17、增加ClickHouse设备数据存储策略支持.(Pro) 18、增加权限过滤功能,可配置禁止赋予自己没有的权限给其他用户.hsweb.permission.filter相关配置 19、设备和产品的租户绑定逻辑优化: 绑定设备时,自动绑定产品.解绑产品时,自动解绑设备.(Pro) 20、用户管理增加租户权限控制.(Pro) 21、当向keepOnline的设备发送消息时,如果原始连接已断开,将返回CONNECTION_LOST错误. 22、设置keepOnline的会话将被持久化,重启服务后自动恢复.(Pro) 23、默认关闭设备最新数据存储,通过jetlinks.device.storage.enable-last-data-in-db=true开启.(Pro) 24、属性物模型增加属性值来源,配置为手动时,在发送修改属性指令(WritePropertyMessage)时,将直接生效,不会发送到设备. 25、优化租户资产解绑逻辑,当删除数据时,解绑资产全部的绑定关系.(Pro) 26、用户管理,机构管理增加租户端支持,租户可以自己管理自己的用户和机构.(Pro)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值