linkedList主要要注意以下几点:

1构造器

2 添加add(E e)

3 获取get(int index)

4 删除 remove(E e),remove(int index)

5  判断对象是否存在:contain(E e)

Jdk8中的linkedList基于双向链表来实现的

双向链表每个结点包含数据域,一个前指针和一个后指针,分别指向前驱结点和后继结点(如果有前驱/后继的话,没有就是null)。

另外,双向链表还有一个first指针,指向头节点,和last指针,指向尾节点。

接下来我们来看看源码

transient int size = 0;

transient Node<E> first; //整个链表的头结点

transient Node<E> last; //整个链表的尾结点

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;
}
}

 如图所示

1构造器

有两个构造器,分别是空的和从一个集合创建。

注意:因为基于链表创建,理论上无容量的限制,不需要扩容的操作。

2 添加add(E e)

默认添加是在链表尾部添加

 public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
//创建一个新结点 并且把尾结点设为当前结点的前驱
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)//如果整个链表为空
first = newNode; //把当前结点设为头结点
else //不为空
l.next = newNode; //把当前结点设为尾结点的后继
size++;
modCount++;
}

  

3 获取get(int index)

public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
// assert isElementIndex(index); if (index < (size >> 1)) { //判断下标位置是在前半截还是后半截 如果在前半截
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next; //从前往后找
return x;
} else { //如果在后半截 Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;// 从后往前找
return x;
}
}
注意:1跟arraylist不同的是,linkedlist查找指定下标元素需要遍历
2 >> 1 (除以2) <<1 (乘以2)

  

4 删除 remove(E e),remove(int index)

 public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) { //先溢出第一个null
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) { //找到了就移除
unlink(x);
return true;
}
}
}
return false;
} E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next; //当前元素的后继
final Node<E> prev = x.prev;//当前元素的前驱 if (prev == null) { //当前元素是头结点
first = next;
} else {
prev.next = next; //设置当前元素的后继为前驱的后继
x.prev = null;
} if (next == null) { //当前元素是尾结点
last = prev;
} else {
next.prev = prev;//设置当前元素的前驱为后继的前驱
x.next = null;
} x.item = null; //清空当前元素
size--;
modCount++;
return element;
}

  

5  判断对象是否存在:contain(E e) 

 public boolean contains(Object o) {
return indexOf(o) != -1;
}
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 {
//从头开始找 看有没有等于item的
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}

  

总结:1 Jdk8中的linkedList基于双向链表来实现的,插入删除快,查询慢,适合读少写多的情况

2 linkedList还有一些有趣的方法,可以实现队列

3添加元素时不用扩容

4 线程不安全

JDK8集合类源码解析 - LinkedList的更多相关文章

  1. JDK8集合类源码解析 - HashSet

    HashSet 特点:不允许放入重复元素 查看源码,发现HashSet是基于HashMap来实现的,对HashMap做了一次“封装”. private transient HashMap<E,O ...

  2. JDK8集合类源码解析 - HashMap

    java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap.Hashtable.LinkedHashMap和TreeMap HashMap ...

  3. JDK8集合类源码解析 - ArrayList

    ArrayList主要要注意以下几点: 1构造方法 2添加add(E e) 3 获取 get(int index) 4 删除 remove(int index)    ,   remove(Objec ...

  4. Java集合类源码解析:Vector

    [学习笔记]转载 Java集合类源码解析:Vector   引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...

  5. Java集合类源码解析:HashMap (基于JDK1.8)

    目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...

  6. 从源码解析LinkedList集合

         上篇文章我们介绍了ArrayList类的基本的使用及其内部的一些方法的实现原理,但是这种集合类型虽然可以随机访问数据,但是如果需要删除中间的元素就需要移动一半的元素的位置,效率低下.并且它内 ...

  7. Java集合类源码解析:ArrayList

    目录 前言 源码解析 基本成员变量 添加元素 查询元素 修改元素 删除元素 为什么用 "transient" 修饰数组变量 总结 前言 今天学习一个Java集合类使用最多的类 Ar ...

  8. Java集合类源码解析:AbstractMap

    目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口 ...

  9. Java集合类源码解析:LinkedHashMap

    前言 今天继续学习关于Map家族的另一个类 LinkedHashMap .先说明一下,LinkedHashMap 是继承于 HashMap 的,所以本文只针对 LinkedHashMap 的特性学习, ...

随机推荐

  1. Numpy:ndarray数据类型和运算

    Numpy的ndarray:一种多维数组对象 N维数组对象,该对象是一个快速而灵活的大数据集容器,nadarry是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的.每个数组都有一个 ...

  2. leetcode 167 two sum II

    167. Two Sum II - Input array is sorted Given an array of integers that is already sorted in ascendi ...

  3. 【C++】Mandelbrot集绘制(生成ppm文件)

    曼德勃罗特集是人类有史以来做出的最奇异,最瑰丽的几何图形.曾被称为"上帝的指纹". 这个点集均出自公式:Zn+1=(Zn)^2+C.(此处Z.C均为复数)所有使得该公式无限迭代后的 ...

  4. 六 json&pickle模块

    之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了 ...

  5. 开发增强现实(AR)教程——识别图的那些坑

    第一期:Vuforia识别图的那些坑 一.Vuforia的图片识别机制 大学时学习的是计算机科学的数字媒体方向,图像处理粗略接触过,对于Vuforia的图片识别机制,只能大概讲一下步骤和猜想,无法给出 ...

  6. unity的inputField文本框赋值问题

    GameObject t = GameObject.Find("InputFieldT"); Text tt = t.transform.Find("Text" ...

  7. 一个先进的App框架:使用Ionic创建一个简单的APP

    原文  http://www.w3cplus.com/mobile/building-simple-app-using-ionic-advanced-html5-mobile-app-framewor ...

  8. linux下安装以及升级npm,node的方法

    1.最开始使用阿里云文档提供的安装方法一直都是失败的状态,后来找到了新的方法重新安装,按照以下操作一步一步的走即可实现,亲测可用 2.安装完之后,会发现npm和node的版本都偏低,需要重新升级以下, ...

  9. python 使用内置方法读取注册表

    #coding:utf-8 import _winreg key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,r"键值") #获取该键的 ...

  10. 使用Python3.x抓取58同城(南京站)的演出票的信息

    #!/usr/bin/env python #-*-coding: utf-8 -*- import re import urllib.request as request from bs4 impo ...