长度一百万的数组,get(0)和get(999999)性能有区别吗?
数组和链表,应该算是最基本的数据结构了吧。
最近在帮公司招人,这个问题我几乎是必问的,然而还是有很多同学答不上来呀,不禁让人唏嘘感慨,基础知识大家还是要多补补哦!
长度一百万的数组,get(0)和get(999999)性能有区别吗?
回答这个问题之前,先来看看数组和链表的一个区别,这样再回过头来看答案时,就会很清晰。
数组
数组(Array)是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 这些有序排列的同类数据元素的集合称为数组。
数组是一种最常用的线性数据结构,它的特点是内存连续,随机访问速度极快。
为什么数组随机访问速度极快?
数组的随机访问速度快,这主要依赖于连续的物理内存。因为内存是连续的,且每个元素占用的空间是等长的,所以不管数组多长,不管访问哪个元素,时间复杂度都是O(1),整个访问过程都只需要两次寻址。
数组的随机访问速度快,但是元素的插入和删除效率较低。
使用ArrayList,插入元素时,插入下标后的所有元素均需要往后移动一位。删除元素时,删除下标后的所有元素均需要向前移动一位。
链表
链表又细分为单向链表、双向链表、循环链表。
单向链表
每个节点维护一个额外的next属性,指向下一个节点。
双向链表
每个节点维护两个额外的属性prev和next,分别指向上一个节点和下一个节点。
循环链表
和双向链表一样,区别是头尾节点是相连的。
链表的优点就是数据的删除、添加速度很快,元素不用移动位置,只需要修改头尾指针的指向就可以了。
缺点是随机访问性能很差,为什么这么说呢?
当使用链表去访问下标数据时,流程大致如下,伪代码:
class Linked{Object data;Linked prev;Linked next;Object get(int index){Linked node = this;while (index > 0) {node = this.next;index--;}return node.data;}
}
链表没有下标,不像数组可以根据下标+步长直接算出元素的内存地址。链表需要通过访问next节点,不断的寻址,一个一个往下找,时间复杂度是O(n)。
数组和链表的性能对比
理论讲完了,该实战一下这两者的性能差距到底几何。
分别创建一百万长度的数组和链表,访问1万次最后的元素:
class Test{static int len = 1000000;public static void main(String[] args) {array();linked();}static void array(){List list = new ArrayList(len);for (int i = 0; i < len; i++) {list.add(i);}long t1 = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {list.get(len-1);}long t2 = System.currentTimeMillis();System.out.println("数组耗时:"+(t2 - t1));}static void linked(){List list = new LinkedList();for (int i = 0; i < len; i++) {list.add(i);}long t1 = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {list.get(len-1);}long t2 = System.currentTimeMillis();System.out.println("链表耗时:"+(t2 - t1));}
}
控制台输出:
What???说好的数组随机访问速度极快呢???怎么没体现出来???
哈哈,别着急,速度没区别是因为JDK对LinkedList.get()
方法做了一些优化。
单纯的访问最后一个元素,数组和链表几乎没区别,都是两次寻址就能定位到元素。
知道原因后,代码改起来就简单了,访问中间的元素不就可以了嘛。
将list.get(len-1)
改为list.get(len/2)
,代码就不重复贴了,再次测试,结果如下:
看到没,效果是不是非常明显,数组耗时1毫秒,而链表用了整整23秒多,碾压式的胜利啊。
而且,链表的耗时会随着List长度的增加而增加,数组不管长度多少,性能都不会波动,原因前面已经说过了。
尾巴
长度一百万的数组,get(0)和get(999999)性能有区别吗?
相信通过这篇文章,我不说答案,大家也都知道了!!!
由于数组的内存是连续的,当需要创建长度很大的集合时,JVM很可能由于找不到一块很大的连续内存而导致内存溢出,这时可以考虑使用链表。
你可能感兴趣的文章:
- AQS源码导读
- 摊牌了,我要手写一个RPC
- Java锁的膨胀过程以及一致性哈希对锁膨胀的影响
- ThreadLocal源码解析
- CMS与三色标记算法
- 大白话理解可达性分析算法
长度一百万的数组,get(0)和get(999999)性能有区别吗?相关推荐
- C++如何定义一个长度超过一百万的数组
在C++中若要设置长度大于1000000的数组,不能在函数内部声明,因为这样属于局部变量,存放在了栈上,容易造成内存溢出. 解决这个问题有两种办法: 1.将数组声明为全局变量: #include< ...
- 2022-12-14:给定一个正数n, 表示从0位置到n-1位置每个位置放着1件衣服 从0位置到n-1位置不仅有衣服,每个位置还摆着1个机器人 给定两个长度为n的数组,powers和rates pow
2022-12-14:给定一个正数n, 表示从0位置到n-1位置每个位置放着1件衣服 从0位置到n-1位置不仅有衣服,每个位置还摆着1个机器人 给定两个长度为n的数组,powers和rates pow ...
- Java编程笔试时输入问题:如何输入固定长度、不定长度的一维数组?如何输入固定长度、不定长度的二维数组?
Java编程笔试时输入问题: 如何输入固定长度.不定长度的一维数组? 如何输入固定长度.不定长度的二维数组? 如何将数组中的内容直接输出,不要中括号和逗号? 文章目录 ==Java编程笔试时输入问题= ...
- 函数中参数有数组时注意的小问题(不一定要传递数组长度,不用返回数组,可以在函数中改变数组元素值)
函数中参数有数组时注意的小问题: 1.不一定要传递数组长度 2.不用返回数组,可以在函数中改变数组元素值 通过下面这个小例子来验证: #include<iostream> #include ...
- C语言中,当计算字符数组长度时,用sizeof 和strlen 的原理及两者的区别
字符数组的长度计算:必须以终止符'/0'作为边界,但对字符数组赋值时,有两种方式: 1: 定义时用字符初始化 (1)char chs[7] = {'a', 'c', '0', 'z', '3','d' ...
- 1、leetcode209 长度最小的子数组
leetcode209 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target . 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+ ...
- 209. Minimum Size Subarray Sum 长度最小的子数组
Title 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度.如果不存在符合条件的连续子数组,返回 0. **示例: ** 输入: ...
- 数组|leetcode209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target . 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, -, numsr-1, numsr] ...
- C语言变长数组data[0]【总结】
C语言变长数组data[0][总结] 1.前言 今天在看代码中遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在li ...
最新文章
- [NC23486]小A与小B 双向广搜
- python能做什么
- Focal Loss笔记
- (原创)无废话C#设计模式之十一:Composite
- PHP开发erp账号登陆问题,浪潮ERP软件E系列创建账套时提示“由于登陆不正确、请重新登陆” | 浪潮888博客...
- 根据输入的日期计算周次和月份
- torchvision学习之torchvision.datasets
- Python中threading的join和setDaemon的区别及用法[例子]
- 程序解析excel中的图片_Excel表格中链接图片操作方法,以后查看图片点点鼠标就可以了...
- 毅航产品—模拟载板I
- 数论学习-初等数论基础总览
- 联想昭阳E46A不能上网
- oracle优化distinct,oracle中使用group by优化distinct
- 论文笔记:NAOMI: Non-Autoregressive MultiresolutionSequence Imputation
- python停止线程_python线程之八:线程停止的3种方式,5个实例
- 一个刁刁的卡片样式广告轮播
- java微信app支付-支付结果通用通知
- 【计算机网络】边缘路由器 三种家庭接入网(光纤到户) DSL、HFC与PON
- SQL Server with as使用
- 【鸽子木 · 每日一题】级数求和(3月31日)
热门文章
- 小字辈 (25 分)
- hdu 5544 Ba Gua Zhen
- 托福高频真词List02 // 附阅读真题
- jsp+springboot使命必达跑腿接单网站系统 ssm
- 快餐连锁店Cava纽交所上市:首日大涨99% 市值49亿美元
- (8)雅思屠鸭第八天:听力中最重要的179个单词(必知必会)
- 利用计算机解决问题过程中找出已知,用计算机解决问题的过程.ppt
- 英语连接词~很全的版本!!!
- 简说Pinterest
- 机器学习【西瓜书/南瓜书】--- 第2章模型评估与选择(上)(学习笔记+公式推导)