• 概述

a, 我们知道LinkedList它的数据存储方式是双向链表,基于链表存储的特性, LinkedList具有查询较慢(顺序访问)但增加/删除较快(虽然要遍历到指定位置, 但是相对于数组存储来说不需要移位)的特点

b, 双向链表的作用, 我们在查询的时候,可以从前往后遍历, 也可以从后往前遍历, 具体使用哪种方式取决于我们要查询的节点是靠后一点还是靠前一点

c, LinkedList内部每个节点用私有内部类Node表示, LinkedList通过first和last引用分别指向链表的第一个和最后一个元素, 当链表为空时, first和last都为null值

d, Node里面有三个元素: item当前节点的值。 next 指向当前节点的后一个节点。prev 指向当前节点的前一个节点

e, LinkedList不存在容量不足的情况。 因为是链表,动态获取内存, 不需要我们去扩容

f, LinkedList可以存储null值

g, LinkedList因为实现了Queue接口, 所以还能当队列使用

  • LinkedList的继承关系

LinkedList 继承自 AbstractSequentialList,同时又实现了 List 和 Deque 接口

从实现上,AbstractSequentialList 提供了一套基于顺序访问的接口。所以LinkedList作为其子类, 也是基于顺序访问。

另外,LinkedList还实现了Deque(double ended queue),Deque又继承自Queue接口。这样LinkedList就具备了队列的功能

  • LinkedList的常用方法

先看构造方法, LinkedList提供了两种构造方法, 无参构造方法会创建一个空的list

public LinkedList(Collection<? extends E> c) 返回一个包含了指定集合的list, 注意这里参数不为空, 否则会抛出空指针异常

LinkedList在查询first和last节点时并不需要遍历, 可以一次定位到对应的节点,然后取出节点的值(item)

同理, 删除first或last节点时也不需要遍历

我们看到这里调用了unlinkFirst和unLinkLast方法, 让我们看看unlink方法做了什么

这里的节点是non-null的, 因为removeFirst()/removeLast()方法里已经做了判空操作

向list的首部或尾部添加元素

上面描述的都是对首节点/尾节点的操作, 并不需要遍历, 因此性能上与arrayList并无区别

接下来看看需要遍历的情况

向指定位置添加元素

我们看到这里首先做了index合法性检查,必须>=0且<=size, 否则会抛出数组越界异常

linkBefore方法也比较简单, 看注释, insert element before non-null node

 那么它是怎么定位到这个non-null  node的呢?

注意这里, 为了提高查询效率, 会先判断index在list中的位置,决定遍历的顺序

当然即便如此, LinkedList的查询效率还是不如Arraylist, 因为ArrayList基于数组存储,不需要遍历

理解了这个方法之后, 其他方法都比较好理解了, 不再赘述

接下来我们重点看看LinkedList的遍历

通常来说,我们遍历一个list有两种方式:

1)普通for循环(下标递增或递减,达到size/0时停止遍历)

public static void main(String[] args)
{
List<Integer> linkedList =
new LinkedList<Integer>(); for (int i = 0; i < 100; i++)
linkedList.add(i);
for (int i = 0; i < 100; i++)
System.out.println(linkedList.get(i));
}
这种方法也可以称为get方法, 因为最终调用了list.get(i)来获取元素
该方法用于ArrayList没有问题, 因为ArrayList基于数组存储, get(i)方法可以直接获得对应的元素, 几乎等同于ArrayList的Iterator, 我们看下源码

return (E) elementData[lastRet = i];  和get(i)方法几乎一样

但是对于LinkedList, 我们在上文中看到get(i)方法需要遍历整个list,这在数据量大的时候将是一个非常耗时的操作

2)使用迭代器

因此对于LinkedList, 我们强烈建议使用迭代器(for each的实现几乎等价于迭代器)

java的collections继承自Iterable接口, 因此所有的集合类都可以使用迭代器进行遍

for(Iterator iter = list.iterator(); iter.hasNext();)

iter.next();

写法非常简便, 而且效率远远高于get方式, 为什么呢?我们看下LinkedList源码

从上面代码中可以看出LinkedList迭代器的next函数只是通过next指针快速得到下一个元素并返回。而get方法会从头遍历直到index下标,查找一个元素时间复杂度为哦O(n),遍历的时间复杂度就达到了O(n2)。
所以对于LinkedList的遍历推荐使用foreach(迭代器),避免使用get方式遍历。

几种其他的遍历方式

如果我们遍历完之后就不再使用这个list了, 我们还可以使用removeFirst()或removeLast()方法,效率更高

try {

while(list.removeFirst() != null) ;

} catch (NoSuchElementException e) {

}

因为LinkedList查询first/last节点时不需要遍历

java集合类之LinkedList的更多相关文章

  1. Java集合类之LinkedList链表

    package com.test; import java.util.*; public class Demo7_3 { public static void main(String[] args) ...

  2. Java集合类学习-LinkedList, ArrayList, Stack, Queue, Vector

    Collection List 在Collection的基础上引入了有序的概念,位置精确:允许相同元素.在列表上迭代通常优于索引遍历.特殊的ListIterator迭代器允许元素插入.替换,双向访问, ...

  3. java集合类之LinkedList详解

    一.LinkedList简介 由于LinkedList是一个实现了Deque的双端队列,所以LinkedList既可以当做Queue,又可以当做Stack,在将LinkedList当做Stack时,使 ...

  4. Java集合类--温习笔记

    最近面试发现自己的知识框架有好多问题.明明脑子里知道这个知识点,流程原理也都明白,可就是说不好,不知道是自己表达技能没点,还是确实是自己基础有问题.不管了,再巩固下基础知识总是没错的,反正最近空闲时间 ...

  5. 做JavaWeb开发不知Java集合类不如归家种地

    Java作为面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储.但是使用数组存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容 ...

  6. 【转载】Java集合类Array、List、Map区别和联系

    Java集合类主要分为以下三类: 第一类:Array.Arrays第二类:Collection :List.Set第三类:Map :HashMap.HashTable 一.Array , Arrays ...

  7. 摘抄转载前辈们的Java集合类总结

    本文摘自 Blue Sky:http://www.cnblogs.com/hubcarl JAVA 集合类介绍和使用 类关系示意图Iterable(接口) │ └--Collection (接口) ├ ...

  8. Java集合类: Set、List、Map、Queue使用场景梳理

    本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E ...

  9. Java 集合类详解(含类图)

    0.参考文献 此图中蓝色为抽象类.深红色表示接口(Arrays除外).绿色表示具体容器类 1.java集合类图 1.1 1.2 上述类图中,实线边框的是实现类,比如ArrayList,LinkedLi ...

随机推荐

  1. Struts2之国际化

    时间:2017-1-11 11:12 --国际化Struts2已经对国际化进行了封装,我们只需要根据其提供的API进行访问即可.要使用国际化的Action必须继承ActionSupport.1.什么是 ...

  2. 恶意软件开发——内存相关API

    一.前言 Windows操作系统的内存有三种属性,分别为:可读.可写.可执行,并且操作系统将每个进程的内存都隔离开来,当进程运行时,创建一个虚拟的内存空间,系统的内存管理器将虚拟内存空间映射到物理内存 ...

  3. 前端 | 页面触底自动加载 Vue 组件

    不管是 web 端还是移动端,信息流都是现在很流行的信息展示方式.信息流经常搭配自动加载一起使用以获得更好的使用体验. 最近在使用 Vue 开发过程中也遇到了首页信息流自动加载的需求.大致了解了一下几 ...

  4. MySQL案例:一次单核CPU占用过高问题的处理

    客户现场反馈,top的检查结果中,一个CPU的占用一直是100%.实际上现场有4个CPU,而且这个服务器是mysql专属服务器. 我的第一反应是io_thread一类的参数设置有问题,检查以后发现re ...

  5. Linux centos7 复制,移动,删除文件或文件夹

    2021-08-121. 文件(文件夹)复制命令 # 命令格式 cp [-adfilprsu] 源文件(source) 目标文件(destination) cp [option] source1 so ...

  6. vue element-ui 组件上传图片 以及对 图片的 宽高 和 大小 格式等 做出限制

    vue  文件: 自行引用 elemen-ui    <el-upload                         action=" 让后端给你上传地址 "      ...

  7. 【曹工杂谈】Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗

    Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗 前奏 我们上篇文章,跟大家说了下,怎么调试maven插件的代码,注意,是插件的代码.插件,是要让主框架来执行的,主框架是谁呢,就是maven ...

  8. scikit-learn 1.0 版本新特性及变动前瞻性预览

    1 简介 就在几天前,著名的机器学习框架scikit-learn在pypi上释放了其1.0rc1版本,这里给大家科普一下,版本号中的rc是Release Candidate的简称,代表当前的版本是一个 ...

  9. 计算机网络参考模型和5G模型的那些事

    一.分层思想 二.OSI参考模型 三.TCP/IP协议族 四.数据封装和解封装过程 五.层间通讯过程 六.3GPP规范及5G协议栈 一.分层思想 享用牛奶的人未必了解其生产过程 使用网络的人未必知道数 ...

  10. js-监听网络状态

    <script> // 监听网络状态 window.addEventListener("online", function(){ alert("网络连接了&q ...