Java中LinkedList的remove方法真的耗时O(1)吗?
这个问题其实来源于Leetcode的一道题目,也就是上一篇日志 LRU Cache。在使用LinkedList超时后,换成ArrayList居然AC了,而问题居然是在于List.remove(Object o)这个方法。
我们知道,链表和数组相比,最主要的特点就是add和remove的操作是O(1)的。Java中的链表一般使用LinkedList这个类型,数组一般使用ArrayList。它们同时implements了List这个interface,所以都有remove(int index)和remove(Object o)这两个方法。
普通意义上认为链表的remove操作是O(1)的,是因为对于某个给定的节点node,可以将它的前置节点的next直接置为node的下一个。而数组,则需要删除index处的元素,再将后面n个元素前移,所以需要O(n)的时间。
但是,在Java中果真如此吗?
细看JDK的源码,就可以发现,LinkedList的remove(int index)和remove(Object o)这两个方法都做不到O(1)的时间,而是O(n)。这是因为上面说的数据结构中的O(1)时间,是对于某个已经确定的节点。而LinkedList中,首先必须通过一个循环,找到第一个出现的Object o,或者走到index这个位置,再进行操作。也就是,有一个get的过程。
这时,虽然ArrayList的remove(int index)和remove(Object o)也是O(n)时间,但是移动耗费的时间远比LinkedList中往后寻址来的快得多,特别是元素很多的时候。JDK的源码里,这个操作是用System.arraycopy()来做的。所以,这时,LinkedList的最为坑爹的地方,也是最令人不解的地方就出现了——remove的操作居然比ArrayList还慢,而且慢的多!
而且,LinkedList需要内部维护一个数据结构,JDK 6中叫Entry,JDK 7中叫Node,这需要很多额外的内存。所以,除非急切需要LinkedList的Deque功能,任何情况下都应该使用ArrayList。其实,即使要用Deque,也有ArrayDeque。
所以,有时面试会问,在一个LinkedList list的遍历for循环中,不断执行remove(i)操作,时间复杂度是多少?其实是O(n^2),而不是O(n)。但是,如果使用iterator,it.remove()的时间复杂度就是O(1)了,因为这时元素已经给定。并且,for循环中进行remove(i)操作是要影响下标的。remove过后每次i都必须i--。使用iterator可以有效避免这个问题。这里可以看到,虽然for循环比较直观,但是有时iterator还是非常好的。
Java中LinkedList的remove方法真的耗时O(1)吗?的更多相关文章
- 转载-Java中LinkedList的一些方法—addFirst addFirst getFirst geLast removeFirst removeLast
Java中LinkedList的一些方法—addFirst addFirst getFirst geLast removeFirst removeLast 版权声明:本文为博主原创文章,遵循CC 4. ...
- java中substring的使用方法
java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...
- Java中Set的contains()方法
Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...
- [java,2017-05-16] java中清空StringBuffer的方法以及耗费时间比较
java中清空StringBuffer的方法,我能想到的有4种: 1. buffer.setLength(0); 设置长度为0 2. buffer.delete(0, buffer.length() ...
- java中BorderLayout的使用方法
相关设置: 使用BorderLayout布局上下左右中布局5个按键,单击中间的那个按键时就关闭窗口 代码: /**** *java中BorderLayout的使用方法 * 使用BorderLayout ...
- 【Java】Java中常用的String方法
本文转载于:java中常用的String方法 1 length()字符串的长度 String a = "Hello Word!"; System.out.println(a.len ...
- Java中Set的contains()方法——hashCode与equals方法的约定及重写原则
转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
- java中static变量和方法的总结
转自:http://blog.csdn.net/haobo920/article/details/5921621 java中static变量和方法的总结 java中一切皆是对象 一个类中对象的定义一般 ...
随机推荐
- .NET中的 枚举
我理解的枚举就是编程中约定的一个"可选值":例如QQ的在线状态,分别有 在线,Q我吧,隐身,忙碌等等...我觉得这就是一个枚举. 1.普通枚举 1) 实例 public en ...
- js 统计字符串中出现次数最多的字符?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 免费GIT托管
http://www.gitcentral.com http://www.projectlocker.com http://gitfarm.appspot.com http://code.google ...
- jeecms获取栏目标题图
[@cms_channel id='1'] <img src="${tag_bean.titleImg!site.typeImg}" /> [/@cms_channel ...
- openerp经典收藏 对象的预定义方法(转载)
对象的预定义方法 原文:http://shine-it.net/index.php/topic,2159.15.html 每个OpenERP的对象都有一些预定义方法,这些方法定义在基类osv.osv中 ...
- 通过数据绑定模板得到对应的Item控件
这类控件都继承于Selector,其中主要有ComboBox.listview.listbox.datagrid. 由于个人对WPF的了解所有可能有遗漏,希望各位能够指出一起进步. 在遍历上面控件时主 ...
- 自己实现的库函数1(strlen,strcpy,strcmp,strcat)
为了便于理解和使用库函数,先把自己实现的几个函数以及测试函数呈现如下. //求字符串长度的函数int my_strlen(const char* pStr){ assert(pStr != NULL) ...
- Linux 挂载2T以上存储
在生产环境中,我们会遇到分区大于2T的磁盘(比如:添加一个3TB的存储),由于MBR分区表只支持2T磁盘,所以大于2T的磁盘必须使用GPT分区表 而fdisk是不支持GPT分区的,我们可以使用part ...
- 谁是最好的Coder
谁是最好的Coder 时间限制:1000 ms | 内存限制:65535 KB 难度:0 描述 计科班有很多Coder,帅帅想知道自己是不是综合实力最强的coder. 帅帅喜欢帅,所以他选了帅 ...
- Http请求和响应应用
//以下载方式打开资源 public void test4(HttpServletResponse response) throws IOException { response.setHeader( ...