LinkedList的一种错误使用方法
近期在做图像处理的时候。发现某一段代码很的慢。慢得让人无法接受。基本的代码是顺序訪问一个LinkedList的元素,效果是随着index的变大,速度越来越慢,list的元素个数在百万以上。找到原因,分享出来。也希望大家不要跳入同一个陷阱。
还是那一句话。可执行的代码和高质量的代码之间还是有比較远的距离。
LinkedList错误使用方法演示样例
代码里面增加了一些打印时间相关的代码,主要是为了直观的显示执行的耗时。
错误代码
public static void main(String[] args) {
// add elements
int size = 2000000;
List<String> list = new LinkedList<String>();
for (int i = 0; i < size; i++) {
list.add("Just some test data");
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
list.get(i);
if (i % 10000 == 0) {
System.out.println("query 10000 elements spend: "
+ (System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
}
}
}
控制台输出例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2lteWxyb25n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
错误原因
错误的代码就是list.get(i),LinkedList的底层是一个链表,随机訪问i的时候。链表仅仅能从头往后数,第i个才返回。所以时间随着i的变大时间会越来越长。
正确使用方法
顺序訪问,LinkedList绝对不要用get方法,即使LinkedList的元素个数仅仅有非常少的几个。
养成好习惯,免得犯错。
for each
for (String element : list) {
// process element here
}
iterator
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String element = iter.next();
// process element here
}
直接换为ArrayList
public static void main(String[] args) {
// add elements
int size = 2000000;
List<String> list = new ArrayList<String>();
for (int i = 0; i < size; i++) {
list.add("Just some test data");
}
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
list.get(i);
if (i % 10000 == 0) {
System.out.println("query 10000 elements spend: "
+ (System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
}
}
}
ArrayList的控制台输出例如以下:
LinkedList VS ArrayList
以下比較一下LinkedList和ArrayList的效率。
新增、查询、删除比較
ArrayList測试代码例如以下:
public static void main(String[] args) {
// add elements
int size = 20000000;
List<String> list = new ArrayList<String>();
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
list.add("Just some test data");
}
System.out.println("add " + size + " elements spend: "
+ (System.currentTimeMillis() - startTime));
// query
startTime = System.currentTimeMillis();
String median = list.get(size / 2);
System.out.println("query median spend: "
+ (System.currentTimeMillis() - startTime));
// delete
startTime = System.currentTimeMillis();
list.remove(median);
System.out.println("delete median spend: "
+ (System.currentTimeMillis() - startTime));
}
LinkedList測试代码例如以下:
public static void main(String[] args) {
// add elements
int size = 20000000;
List<String> list = new LinkedList<String>();
long startTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
list.add("Just some test data");
}
System.out.println("add " + size + " elements spend: "
+ (System.currentTimeMillis() - startTime));
// query
startTime = System.currentTimeMillis();
String median = list.get(size / 2);
System.out.println("query median spend: "
+ (System.currentTimeMillis() - startTime));
// delete
startTime = System.currentTimeMillis();
list.remove(median);
System.out.println("delete median spend: "
+ (System.currentTimeMillis() - startTime));
}
各自特点
- 新增
ArrayList比LinkedList快非常多,超过一个数量级。非常是意外。
- 随机查询
在i值非常大的时候,ArrayList比LinkedList快非常多,i越大,差距越大。ArrayList底层是数组。随机訪问时间效率是O(0),而LinkedList是O(n)。 - 删除
LinkedList比ArrayList快非常多。LinkedList的删除操作时间效率为O(0)。而ArrayList是O(n),ArrayList须要查找数据、移动数据,所以慢。
总结
尽量使用ArrayList,ArrayList满足不了需求的时候再用LinkedList。依据LinkedList的特点,在以下几种情况下才使用LinkedList。
- 须要使用
java.util.List接口之外的API
LinkedList实现了Queue和Stack等接口,能够用来当作一些特殊的容器。吐槽JDK里面LinkedList的设计,塞太多东西了,和名字不符。 - 元素删除比較频繁
假设数据量大,删除频繁,仅仅能用LinkedList。 - 内存碎片化且元素非常多
ArrayList底层是一个数组,数组要求一段连续的内存快。LinkedList也能够充分利用内存的一些碎片。特别是JVM使用Concurrent Mark-Sweep Collector垃圾回收器的时候,显得尤为重要。
LinkedList的一种错误使用方法的更多相关文章
- vs------各种错误解决方法
错误:命名空间System.Net中不存在类型或命名空间名“Http”,或工程里面“引用”的文件太少 转载:http://www.asp.net/mvc/mvc4 错误:LD.exe 已退出,代码为- ...
- Modbus通讯错误检测方法
标准的Modbus串行网络采用两种错误检测方法.奇偶校验对每个字符都可用,帧检测(LRC和CRC)应用于整个消息.它们都是在消息发送前由主设备产生的,从设备在接收过程中检测每个字符和整个消息帧. 用户 ...
- 笔记:php有那几种错误提示和查错方法
php有哪几种错误提示 1.notice : 注意 2.waring : 警告 3.error : 错误 PHP中都有哪几种查错方法? 1.语法检查--php配置文件里,把错误显示选项都打开或者代码开 ...
- mysql Access denied for user root@localhost错误解决方法总结(转)
mysql Access denied for user root@localhost错误解决方法总结(转) mysql Access denied for user \'root\'@\'local ...
- ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)
主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...
- ArrayList和LinkedList的几种循环遍历方式及性能对比分析
最新最准确内容建议直接访问原文:ArrayList和LinkedList的几种循环遍历方式及性能对比分析 主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性 ...
- JAVA常见错误处理方法 和 JVM内存结构
OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...
- eWebeditor编辑器上传图片路径错误解决方法[疑难杂症]【转,作者:unvs】
做了一个多版本的网站,后台用的编辑器是eWebeditor,NET版,后面发现上传图片或者文件之后,路径错误无法显示,必须手工修改才行.. 为了更清楚的说明问题,我下面会说的比较详细,首先是网站文件框 ...
- ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转载)
原文地址: http://www.trinea.cn/android/arraylist-linkedlist-loop-performance/ 原文地址: http://www.trinea.cn ...
随机推荐
- 数据结构--汉诺塔--借助栈实现非递归---Java
/*汉诺塔非递归实现--利用栈 * 1.创建一个栈,栈中每个元素包含的信息:盘子编号,3个塔座的变量 * 2.先进栈,在利用循环判断是否栈空, * 3.非空情况下,出栈,检查是否只有一个盘子--直接移 ...
- Python的高级特性(切片,迭代,生成器,迭代器)
掌握了python的数据类型,语句和函数,基本上就可以编出很多有用的程序了. 但是在python中,并不是代码越多越好,代码不是越复杂越好,而是越简单越好. 基于这个思想,就引申出python的一些高 ...
- ie8以下浏览器注意事项
ie8以下ajax请求或者socket请求时一定要加二级域名:(目的不能垮域访问)
- PLM_百度百科
PLM_百度百科 ZDLINK
- jvm分析内存泄露
首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 - 导航条 - 首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 ...
- MySql_安装及简单命令
一.下载MySql http://dev.mysql.com/downloads/file/?id=461390 版本位5.7.11.0.msi,32位的,但是该版本在64位机器上也可以使用 二.安装 ...
- Android记一次后台保活设计心得2018
首先我并不推荐也不喜欢手机应用通过各种手段后台保活,但是当产品经理确定一定以及肯定地提出了这个需求,活着应用有着必须常驻后台的理由,也就只有硬着头皮去与各个手机的后台管理机制做斗争了. 背景:因为开发 ...
- jenkins的slave没有执行build,slave执行build失败
1.slave的build配置如下 2.但是从控制台输出日志来看,pre steps和post steps都执行了,但是build没有执行 3.最后的错误信息如下: ERROR: Failed to ...
- 二十四种设计模式:观察者模式(Observer Pattern)
观察者模式(Observer Pattern) 介绍定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新. 示例有一个Message实体类,某些对象 ...
- String格式化参数整理
Java String格式话参数整理如下: conversion:转换格式,可选的格式有: d 整数型(十进制) c Unicode字符 b Boolean值 s String f 浮点数(十进制) ...