list是个一唯的线性存储容器。我们可以把它比喻成一个竹签子,你可以把山楂、橘子串在上面,也可以把鸡翅、羊肉串在上面。吃的时候你可以从头、尾或者中间任何地方下口。

我们下面着重介绍下两个常用的实现,ArrayList和LinkedList。

ArrayList

arraylist顾明思议就是通过数组这种数据结构实现的list。数组的实现可以让它从任意的位置读取数据,也可以把数据写入数组的任意位置,但由于数组需要指定长度,所以会有扩容的问题。

LinkedList

LinkedList是通过链表实现的list。它的每个节点都会存储前一个和后一个节点的指针,每个list还会存储头和尾两个指针,所以它不能直接读取指定位置,但不会有扩容的问题。

list的主要场景有4个,顺序写、随机写、顺序读和随机读,下面我们从这4个场景模拟分析下这两种实现的不同点。

1.顺序写

ArrayList

//我们先初始化一个ArrayList, 这时arraylist会帮我们初始化一个长度为10的数组

List list = new ArrayList();

因为数组初始化必须指定长度,所以我们创建ArrayList时就会创建一个定长数组。

//这时我们把调用add方法把1写入到list中

list.add("A");

因为arraylist会保存index,所以add方法只是把数组的index位赋值为A,index加1就可以了。

//这时我们把调用add方法把B写入到list中

list.add("B");

填加B也是同理

LinkedList

//我们先初始化一个LinkedList,初始化时LinkedList并不会做什么

List list = new LinkedList();

//这时我们把调用add方法把A写入到list中

list.add("A");

这时的linkedlist的头指针和尾指针同时指向A

//我们再调用add方法把B写入到list中

list.add("B");

当调用add方法时,因为尾指针指向的是A节点,所以把A节点的next节点指向B,同时尾节点指向B

2.随机写

Arraylist

//我们再调用add方法把C写入到list中

list.add(2, "C");

所以ArrayList的随机写时间复杂度为O(n)

LinkedList

//我们再调用add方法把C写入到list中

list.add(2, "C");

linkedlist虽然不需要做节点移动,但是他要通过A、B、D节点这样遍历的方式找打插入的位置,所以时间复杂度也为O(n)

3.顺序读

Arraylist

在访问arraylist中任意一个元素的时候,因为底层实现是数组,所以都可以直接读取,时间复杂度为O(1)。

LinkedList

使用迭代器读取linkedlist,迭代器会维护一个当前节点的指针,所以也不需要循环查找,时间复杂度为O(1)。

4.随机读

Arraylist

arraylist的随机读通过底层数组支持,时间复杂度为O(1)。

LinkedList

linkedlist的随机读则只能通过从头循环遍历的方式查找,所以时间复杂度为O(n)

5.ArrayList的扩容

数组因为长度固定,所以当数组已经存满的时候就需要扩容。

如图所示,当D插入到arraylist时,发现数组已满,这时arraylist就会新建一个数组,长度是原来的2倍,并把原数组的数据移动到新数组,再把D插入到新数组中。

最后我们对比下这两个实现的时间复杂度。

时间复杂度

ArrayList

LinkedList

顺序写

O(1)

O(1)

随机写

O(n)

O(n)

顺序读

O(1)

O(1)

随机读

O(1)

O(n)

总结下我们应该如果选择

如果数据大小固定,需要随机读取使用ArrayList

如果数据大小不确定,不需要随机读取,使用LinkedList

java list主要实现_java容器-list的常用实现及原理相关推荐

  1. java中的集合_Java 集合介绍,常用集合类

    JAVA 集合 在处理数据的过程中经常会需要一个容器来存储某一类型的数据,Java 中的数组就是这样一种容器.但 Java 中的数组有其局限性,定义后的数组长度不可变,超出数组长度后就不能再存放数据了 ...

  2. java 建树源码_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...

    import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; //二叉树的建树,前中后 递归非递归遍历 层序 ...

  3. java dump分析工具_java性能分析与常用工具

    本次源码已放在Github:https://github.com/nateshao/jvm-tuning 个人博客 https://nateshao.gitee.io http://www.nates ...

  4. java 多线程间通讯_JAVA多线程间通讯常用实现方法解析

    如何实现线程间通讯,有如下三种方法: 1.使用Semaphore (信号量)类来控制线程的等待和释放 功能:三个线程 a .b .c 并发运行,b,c 需要 a 线程的数据怎么实现 分析:考虑到多线程 ...

  5. java 实现 web 客户端_Java web客户端和服务器端交互的原理

    Java web客户端和服务器端交互的原理 其实HTTP客户端和服务器端的交互原理很简单:即先是浏览器和服务器端建立Socket无状态连接,也就是短连接,然后通过IO流进行报文信息(这个报文是严格遵循 ...

  6. java regex match 替换_java正则表达式四种常用的处理方式(匹配、分割、替代、获取)...

    java 正则表达式高级篇,介绍四种常用的处理方式:匹配.分割.替代.获取,具体内容如下 package test; import java.util.regex.Matcher; import ja ...

  7. java语言冒泡排序法_Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等...

    本文实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 .快速排序.归并排序.堆排序和LST基数排序 首先是EightAlgorithms.java文件,代码如下: import jav ...

  8. java date类 时区_Java时区转换及Date类实现原理解析

    这篇文章主要介绍了Java时区转换及Date类实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.时区的说明 地球表面按经线从东到西,被 ...

  9. java增强for循环_Java中增强for循环的实现原理和坑详解

    前言 引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需要先获得数组的长度或集合的迭代器,比较麻烦. JDK5中定义了一种新的语法----增强for循环,以简化此类操作.增强 ...

最新文章

  1. python 字典 的pop 方法
  2. 计算机初级学哪个公需课,西安职称评审申报你遇到以下问题了吗?
  3. lnmp/nginx系统真正有效的图片防盗链完整设置详解
  4. opencv+dlib人脸关键点检测cpp版
  5. openlayers基础(一)——Map
  6. CSS-非常有用的css变量
  7. QIPAIFANS网站程序【2013最新版】
  8. 7-68 求整数段和 (15 分)
  9. 为什么我们没有选择Rust?
  10. 加州理工学院公开课:机器学习与数据挖掘_过拟化
  11. 打开你企业发展之门的钥匙
  12. c语言tc2.0编译器下载,c语言编译器|c语言编译器(wintc)_绿茶手机网
  13. win2003服务器360修复漏洞打不开网页,win7电脑使用360浏览器打不开网页的有效恢复方法...
  14. 进击的Libra:路在何方?中国应如何应对?
  15. 教你如何关闭Win7视频预览节约资源
  16. 2-3、迭代法计算定积分
  17. excel柱形图/条形图怎能给正负值填充不同的颜色
  18. python绘制饼图
  19. 假如生活欺骗了你-普希金
  20. 基于VUE + Echarts 实现可视化数据大屏旅游大数据

热门文章

  1. Oracle系统结构之修改oracle内存参数
  2. 【剑指offer】丑数
  3. bootstrap-wysiwyg: 迷你的Bootstrap的所见即所得的HTML富文本编辑器
  4. C#入门篇5-6:流程控制语句 foreach
  5. apache的日志级别和设置
  6. postgres创建用户,修改用户密码,创建数据库
  7. linux docker搭建 minecraft 我的世界游戏服务器
  8. python 网络相关依赖库 dpkt、scapy、pcap 安装
  9. docker logs 查看docker容器日志
  10. python3 赋值与内存空间