1.数据结构-链表

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表的类型:

  • 单向链表:单向链表包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。

  • 双向链表:双向链表每个节点有两个连接:一个指向前一个节点,(当此“连接”为第一个“连接”时,指向空值或者空列表);而另一个指向下一个节点,(当此“连接”为最后一个“连接”时,指向空值或者空列表)

  • 循环链表:在一个循环链表中, 首节点和末节点被连接在一起。

2.ArrayList结构特性

LinkedList 与 ArrayList 一样实现 List 接口,只是 ArrayList 是 List 接口的大小可变数组的实现,LinkedList 是 List 接口链表的实现。有以下特性:

  • 允许包含重复的元素
  • 允许包含null元素
  • 保存了元素添加的顺序
  • 不是线程安全的

3.构造方法

  1. // 1.构造一个空列表
  2. LinkedList()
  3. // 2.构造一个包含指定集合元素的列表
  4. LinkedList(Collection<? extends E> c)

4.成员变量

  1. // 1.链表中的元素数
  2. transient int size
  3. // 2.指向第一个元素的指针
  4. transient Node<E> first
  5. // 3.指向最后一个元素的指针
  6. transient Node<E> last

5.常用的成员方法

  1. // 1.添加一个元素到列表的尾部
  2. boolean add(E e)
  3. // 2.添加一个元素到列表的指定位置
  4. void add(int index, E element)
  5. // 3.将指定集合中的所有元素追加到此列表的末尾。
  6. boolean addAll(Collection<? extends E> c)
  7. // 4.添加一个元素到列表的头部
  8. void addFirst(E e)
  9. // 5.添加一个元素到列表的尾部
  10. addLast(E e)
  11. // 6.检查列表中包含指定的元素
  12. boolean contains(Object o)
  13. // 7.返回列表的第一个元素
  14. E element()
  15. // 8.返回列表指定位置的元素
  16. E get(int index)
  17. // 9.返回指定元素在列表中首次出现的索引
  18. int indexOf(Object o)
  19. // 10.返回指定元素在列表中最后一次出现的索引
  20. int lastIndexOf(Object o)
  21. // 11.添加一个元素到列表的尾部
  22. boolean offer(E e)
  23. // 12.返回列表的第一个元素
  24. E peek()
  25. // 13.删除并返回此列表的第一个元素
  26. E poll()
  27. // 14.删除并返回此列表的第一个元素
  28. E pop()
  29. // 15.添加一个元素到列表的头部
  30. void push(E e)
  31. // 16.移除列表的第一个元素
  32. E remove()
  33. // 17.设置指定位置的元素
  34. E set(int index, E element)
  35. // 18.返回列表中的元素数
  36. int size()
  37. // 19.返回一个数组,包含列表中所有元素
  38. Object[] toArray()

6.Node节点

  1. // LinkedList的静态内部类
  2. private static class Node<E> {
  3. // 节点的值
  4. E item;
  5. // 下一个节点的引用
  6. Node<E> next;
  7. // 上一个节点的引用
  8. Node<E> prev;
  9. // 初始化一个节点的值,保存上一个节点和下一个节点的引用
  10. Node(Node<E> prev, E element, Node<E> next) {
  11. this.item = element;
  12. this.next = next;
  13. this.prev = prev;
  14. }
  15. }

7.序列化原理

1.LinkedList 实现了Serializable接口,支持对象序列化

  1. public class LinkedList<E>
  2. extends AbstractSequentialList<E>
  3. implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  4. {
  5. ......
  6. }

2.序列化时调用 writeObject 方法,将 size 和 node 节点列表写入 ObjectOutputStream。

  1. private void writeObject(java.io.ObjectOutputStream s)
  2. throws java.io.IOException {
  3. // Write out any hidden serialization magic
  4. s.defaultWriteObject();
  5. // 序列化 size
  6. s.writeInt(size);
  7. // 从第一个元素开始,将链表中所有的元素序列化
  8. for (Node<E> x = first; x != null; x = x.next)
  9. s.writeObject(x.item);
  10. }

3.反序列化时调用 readObject 方法,恢复 size 和 node 节点列表。

  1. private void readObject(java.io.ObjectInputStream s)
  2. throws java.io.IOException, ClassNotFoundException {
  3. // Read in any hidden serialization magic
  4. s.defaultReadObject();
  5. // 恢复size
  6. int size = s.readInt();
  7. // 恢复链表
  8. for (int i = 0; i < size; i++)
  9. linkLast((E)s.readObject());
  10. }

4.成员变量 size、first 和 last 使用 transient 关键字修饰,不会序列化到目的地中,从而节省时间和空间。

8.迭代器

1.由LinedList内部类ListItr实现ListIterator 接口,间接实现Iterator 接口。

  1. public ListIterator<E> listIterator(int index) {
  2. checkPositionIndex(index);
  3. return new ListItr(index);
  4. }
  5. private class ListItr implements ListIterator<E> {
  6. // 最近返回的节点引用
  7. private Node<E> lastReturned;
  8. // 下一个节点的引用
  9. private Node<E> next;
  10. // 下一个节点的位置索引
  11. private int nextIndex;
  12. private int expectedModCount = modCount;
  13. ......
  14. }

2.ListItr实现迭代器的成员方法

  1. // 检查指针索引指向链表的边界
  2. public boolean hasNext() {
  3. return nextIndex < size;
  4. }
  5. // 返回next 指向的节点,同时next偏移下一个节点
  6. public E next() {
  7. ......
  8. }
  9. // 移除最近返回的节点(lastReturned引用)
  10. public void remove() {
  11. ......
  12. }

9.总结

以上就是对LinkedList的理解,如果有不正确的地方,欢迎指正,最后,补一张脑图:

Java集合-LinkedList源码分析的更多相关文章

  1. Java入门系列之集合LinkedList源码分析(九)

    前言 上一节我们手写实现了单链表和双链表,本节我们来看看源码是如何实现的并且对比手动实现有哪些可优化的地方. LinkedList源码分析 通过上一节我们对双链表原理的讲解,同时我们对照如下图也可知道 ...

  2. Java集合---LinkedList源码解析

    一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clo ...

  3. Java集合——LinkedList源码详解

    )LinkedList直接继承于AbstractSequentialList,同时实现了List接口,也实现了Deque接口. AbstractSequentialList为顺序访问的数据存储结构提供 ...

  4. Java集合框架源码分析(2)LinkedList

    链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...

  5. java.util.LinkedList源码分析

    public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, D ...

  6. java中LinkedList源码分析

    ArrayList是动态数组,其实本质就是对数组的操作.那么LinkedList实现原理和ArrayList是完全不一样的.现在就来分析一下ArrayList和LinkeList的优劣吧LinkedL ...

  7. Java集合-ArrayList源码分析

    目录 1.结构特性 2.构造函数 3.成员变量 4.常用的成员方法 5.底层数组扩容原理 6.序列化原理 7.集合元素排序 8.迭代器的实现 9.总结 1.结构特性 Java ArrayList类使用 ...

  8. java集合系列之LinkedList源码分析

    java集合系列之LinkedList源码分析 LinkedList数据结构简介 LinkedList底层是通过双端双向链表实现的,其基本数据结构如下,每一个节点类为Node对象,每个Node节点包含 ...

  9. Java集合之LinkedList源码分析

    概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差 ...

随机推荐

  1. CF667A Pouring Rain 题解

    Content 一个水桶直径为 \(d\) 厘米,初始时水面高度为 \(h\) 厘米.你每秒钟喝 \(v\) 毫升水,而由于下雨,水桶里面的水在不喝水的时候每秒会上升 \(e\) 厘米.求你最少需要多 ...

  2. Birt报表设置自定义的值

    比如数据库查出该字段的值有"no",有"yes",那么想要根据当是no是显示"未完成",当是yes时显示"已完成" 可以 ...

  3. 20款GitHub上优秀的Go开源项目

    docker 无人不知的虚拟华平台,开源的应用容器引擎,借助该引擎,开发者可以打包他们的应用,移植到任何平台上. https://github.com/docker/docker 38154 star ...

  4. jQuery 实现列表自动滚动循环滚动显示新闻通知

    需求 页面中一个小区域循环滚动展示通知(公告.新闻.活动.图片等),并且鼠标hover时停止滚动并提示,鼠标离开后,继续滚动. 效果图 https://www.iguopin.com/index.ph ...

  5. git pull 拉取报错:fatal: refusing to merge unrelated histories

    fatal: refusing to merge unrelated histories(拒绝合并不相关的历史) 使用 git pull origin master --allow-unrelated ...

  6. python 安装模块报错 response.py", line 302, in _error_catcher

    python 安装模块报错 Exception:Traceback (most recent call last): File "/usr/share/python-wheels/urlli ...

  7. Linux使用docker安装Jenkins 并进行jar包发布

    拉取镜像 docker pull jenkins/jenkins:lts 创建docker-compose.yml 文件 (主要习惯 也可以不用这种方式)  Linux安装docker-compose ...

  8. c++读取文件操作和写入文件

    在C++中与读取文件和写入文件简单操作有关的类分别有ifstream(文件读入).ofstream(文件写出).fstream (文件读入和写出). 名称 作用 ifstream 文件读入 ofstr ...

  9. 【LeetCode】424. 替换后的最长重复字符 Longest Repeating Character Replacement(Python)

    作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 本文关键词:LeetCode,力扣,算法,算法题,字符串,双指针,刷题群 目录 题目描述 题目大意 解题方法 双指针 代码 欢迎 ...

  10. Spring Boot实战一:搭建Spring Boot开发环境

    一开始接触Spring Boot就感到它非常强大,也非常简单实用,遂想将其记录下来. 搭建Spring Boot工程非常简单,到:http://start.spring.io/ 下载Spring Bo ...