java集合部分:如何理解LinkedList?

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

链表可分为单向链表和双向链表。

一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。

一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。

Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。

与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。

以下情况使用 ArrayList :

  • 频繁访问列表中的某一个元素。
  • 只需要在列表末尾进行添加和删除元素操作。

以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

LinkedList 继承了 AbstractSequentialList

{AbstractSequentialList 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。}

LinkedList 实现了 Queue 接口Queue接口与List、Set同一级别,都是继承了Collection接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用,可作为队列使用

{

队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进

行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为

空队列。

  队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个

元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添

加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,

阻塞队列是很有用的工具。工作者线程可 以定期地把中间结果存到阻塞队列中而其他工作者线线

程把中间结果取出并在将来修改它们。队列会自动平衡负载。如果第一个线程集运行得比第二个

慢,则第二个 线程集在等待结果时就会阻塞。如果第一个线程集运行得快,那么它将等待第二个

线程集赶上来。下表显示了jdk1.5中的阻塞队列的操作:

add        增加一个元索                     如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove   移除并返回队列头部的元素    如果队列为空,则抛出一个NoSuchElementException异常
element  返回队列头部的元素             如果队列为空,则抛出一个NoSuchElementException异常
offer       添加一个元素并返回true       如果队列已满,则返回false
poll         移除并返问队列头部的元素    如果队列为空,则返回null
peek       返回队列头部的元素             如果队列为空,则返回null
put         添加一个元素                      如果队列满,则阻塞
take        移除并返回队列头部的元素     如果队列为空,则阻塞

remove、element、offer 、poll、peek 其实是属于Queue接口。 

  Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,

使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法

在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。

  值得注意的是LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。

}

LinkedList 实现了 List 接口,可进行列表的相关操作

{

List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索

引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许

有相同的元素。

List 接口存储一组不唯一,有序(插入顺序)的对象。

}

LinkedList 实现了 Deque 接口,可作为队列使用

{

Deque(java.util.Deque)接口代表着双向队列,意思就是可以从队列的两端增加或者删除元素,

Deque就是双向Queue的意思。

}

LinkedList 实现了 Cloneable 接口,可实现克隆

{

Cloneable接口是Java开发中常用的一个接口, 它的作用是使一个类的实例能够将自身拷贝到另一

个新的实例中,注意,这里所说的“拷贝”拷的是对象实例,而不是类的定义,进一步说,拷贝的是

一个类的实例中各字段的值。

在开发过程中,拷贝实例是常见的一种操作,如果一个类中的字段较多,而我们又采用在客户端中

逐字段复制的方法进行拷贝操作的话,将不可避免的造成客户端代码繁杂冗长,而且也无法对类中

的私有成员进行复制,而如果让需要具备拷贝功能的类实现Cloneable接口,并重写clone()方法,

就可以通过调用clone()方法的方式简洁地实现实例拷贝功能。

}

LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输

{

Serializable接口概述

Serializable是java.io包中定义的、用于实现Java类的序列化操作而提供的一个语义级别的接口。

Serializable序列化接口没有任何方法或者字段,只是用于标识可序列化的语义(用于标识可序列

化的VO类。实现Serializable接口的类可以被ObjectOutputStream转换为字节流,同时也可以通

过ObjectInputStream再将其解析为对象。例如,我们可以将序列化对象写入文件后,再次从文件

中读取它并反序列化成对象,也就是说,可以使用表示对象及其数据的类型信息字节在内存中重

新创建对象

序列化:把原本在内存中的对象状态 变成可存储或传输的过程称之为序列化。序列化之后,就可

以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。序列化前的对象和反序列化后得

到的对象,内容是一样的(且对象中包含的引用也相同),但两个对象的地址不同。换句话说,序列

化操作可以实现对任何可Serializable对象的”深度复制(deep copy)"。

通俗理解序列化与反序列化:以搬桌子为例,桌子太大了不能通过比较小的门,我们要把它拆了再

运进去,这个拆桌子的过程就是序列化。同理,反序列化就是等我们需要用桌子的时候再把它组合

起来,这个过程就是反序列化。

什么情况下需要序列化?

a)当你想把的内存中的对象状态保存到一个文件中或者数据库中,以便可以在以后重新创建精确

的副本;

b)当你想用套接字在网络上传送对象的时候(从一个应用程序域发送到另一个应用程序域中);

c)当你想通过RMI传输对象的时候;

注意事项:

a)序列化时,只对对象的状态进行保存,而不管对象的方法;
b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化
d)并非所有的对象都可以序列化
e) 序列化会忽略静态变量,即序列化不保存静态变量的状态静态成员属于类级别的,不能序列化。添加了static、transient关键字后的变量不能序列化。

}

LinkedList 类位于 java.util 包中,使用前需要引入它,语法格式如下:

// 引入 LinkedList 类
import java.util.LinkedList; 

LinkedList<E> list = new LinkedList<E>();   // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表

{

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针

链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态

生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指

针域。

链表与数组的区别

数组,是相同数据类型的元素按一定顺序排列的集合。根据概念我们可以知道数组在内存中连续,

链表不连续;由于不同的存储方式导致数组静态分配内存,链表动态分配内存,数组元素在栈区,

链表元素在堆区;由于数组在内存中连续,我们可以利用下标定位,时间复杂度为O(1),链表定位

元素时间复杂度O(n);但是由于数组的连续性数组插入或删除元素的时间复杂度O(n),链表的时间

复杂度O(1)。

总结一下,数组和链表的区别如下
  1.数组静态分配内存,链表动态分配内存
  2.数组在内存中连续,链表不连续
  3.数组元素在栈区,链表元素在堆区
  4.数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
  5.数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。

存储数据主要是线性结构、链式结构。

线性结构也叫顺序结构,他是把相邻的节点存储在物理位置相邻的存储单元里,通常借助于程序设

计中的数组方式来具体实现,所以对应的,数组存储的优缺点也是线性结构存储的优缺点。下面再

详细说说两种存储方式的优缺点。

链式结构,它不要求逻辑上相邻的节点在物理位置上也相邻,节点间的逻辑关系是由附加的指针字

段表示的,通常借助于程序设计中的指针结构来实现。

线性结构的优点是可以实现随机读取,时间复杂度为O(1),空间利用率高,缺点是进行插入和删除

操作时比较麻烦,时间复杂度为O(n),同时容量受限制,需要事先确定容量大小,容量过大,浪费

空间资源,过小不能满足使用要求,会产生溢出问题

链式存储结构的优点主要是插入和删除非常简单,前提条件是知道操作位置,时间复杂度是O(1),

但如果不知道造作位置则要定位元素,时间复杂度为O(n),没有容量的限制,可以使用过程中动态

分配的分配内存空间,不用担心溢出问题,但是它并不能实现随机读取,同时空间利用率不高

}

常用方法

方法描述
public boolean add(E e)链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
public void add(int index, E element)向指定位置插入元素。
public boolean addAll(Collection c)将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。
public boolean addAll(int index, Collection c)将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。
public void addFirst(E e)元素添加到头部。
public void addLast(E e)元素添加到尾部。
public boolean offer(E e)向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
public boolean offerFirst(E e)头部插入元素,返回是否成功,成功为 true,失败为 false。
public boolean offerLast(E e)尾部插入元素,返回是否成功,成功为 true,失败为 false。
public void clear()清空链表。
public E removeFirst()删除并返回第一个元素。
public E removeLast()删除并返回最后一个元素。
public boolean remove(Object o)删除某一元素,返回是否成功,成功为 true,失败为 false。
public E remove(int index)删除指定位置的元素。
public E poll()删除并返回第一个元素。
public E remove()删除并返回第一个元素。
public boolean contains(Object o)判断是否含有某一元素。
public E get(int index)返回指定位置的元素。
public E getFirst()返回第一个元素。
public E getLast()返回最后一个元素。
public int indexOf(Object o)查找指定元素从前往后第一次出现的索引。
public int lastIndexOf(Object o)查找指定元素最后一次出现的索引。
public E peek()返回第一个元素。
public E element()返回第一个元素。
public E peekFirst()返回头部元素。
public E peekLast()返回尾部元素。
public E set(int index, E element)设置指定位置的元素。
public Object clone()克隆该列表。
public Iterator descendingIterator()返回倒序迭代器。
public int size()返回链表元素个数。
public ListIterator listIterator(int index)返回从指定位置开始到末尾的迭代器。
public Object[] toArray()返回一个由链表元素组成的数组。
public T[] toArray(T[] a)返回一个由链表元素转换类型而成的数组。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_GGI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值