这个问题其实来源于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)吗?的更多相关文章

  1. 转载-Java中LinkedList的一些方法—addFirst addFirst getFirst geLast removeFirst removeLast

    Java中LinkedList的一些方法—addFirst addFirst getFirst geLast removeFirst removeLast 版权声明:本文为博主原创文章,遵循CC 4. ...

  2. java中substring的使用方法

    java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...

  3. Java中Set的contains()方法

    Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...

  4. [java,2017-05-16] java中清空StringBuffer的方法以及耗费时间比较

    java中清空StringBuffer的方法,我能想到的有4种: 1. buffer.setLength(0);  设置长度为0 2. buffer.delete(0, buffer.length() ...

  5. java中BorderLayout的使用方法

    相关设置: 使用BorderLayout布局上下左右中布局5个按键,单击中间的那个按键时就关闭窗口 代码: /**** *java中BorderLayout的使用方法 * 使用BorderLayout ...

  6. 【Java】Java中常用的String方法

    本文转载于:java中常用的String方法 1 length()字符串的长度 String a = "Hello Word!"; System.out.println(a.len ...

  7. Java中Set的contains()方法——hashCode与equals方法的约定及重写原则

    转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...

  8. java中equals和hashCode方法随笔二

    前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...

  9. java中static变量和方法的总结

    转自:http://blog.csdn.net/haobo920/article/details/5921621 java中static变量和方法的总结 java中一切皆是对象 一个类中对象的定义一般 ...

随机推荐

  1. daxuez.com

    大学z,一个还没想好的名字和项目 初期定位:服务于武汉各大高校的大学学生群体 服务项目:兼职.旅游.培训.租车.班服订做.票务

  2. WPF 绑定一(数据源为控件)

    xaml: <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.co ...

  3. webview的弹性布局之rem,em

    webview页面的自适应一般有两种方法,即一是JS的计算方法,二是通过css的media设置分档方式.在此主要介绍css的方式. html { font-size: 16px; } @media o ...

  4. [大牛翻译系列]Hadoop(22)附录D.2 复制连接框架

    附录D.2 复制连接框架 复制连接是map端连接,得名于它的具体实现:连接中最小的数据集将会被复制到所有的map主机节点.复制连接的实现非常直接明了.更具体的内容可以参考Chunk Lam的<H ...

  5. 如何修改 Discuz 门户文章页默认视频大小

    在 Discuz 系统中,论坛插入 Flash 等可以输入自定义的尺寸,但是门户文章页不可以修改.经过一番研究,找到了修改门户文章页默认视频大小的方法如下,希望对你有用:找到:/source/func ...

  6. java 环境变量设置

    JAVA_HOME  C:\Program Files\Java\jdk1.7.0 PATH %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; CLASSPATH .;%JAV ...

  7. oracle 11g 通过透明网关链接mysql

    之前转载过一篇在Windows上安装的,自己实际在centos上安装了一下.以下为安装记录: 一.操作系统环境 二.数据库环境(用oracle用户登录) 三.DG4ODBC 在Oracle DB 11 ...

  8. Window.ActiveXObject的用法 以及如何判断浏览器的类型

    (window.ActiveXObject) 什么意思? 解:判断浏览器是否支持ActiveX控件,如果浏览器支持ActiveX控件可以利用 var xml=new ActiveXObject(&qu ...

  9. C#的winform拼数字游戏

    C#的winform拼数字游戏 声明:阅读了别人的代码学习修改而来,增加了美观度和游戏乐趣.(作者出处忘了不好意思) 程序截图 关键代码 using System; using System.Coll ...

  10. ASP.NET Web - 回送

    如果希望把更改事件立即传送给服务器,可以把AutoPostback属性设置为true.这样就会使用客户端的JavaScript把窗体数据立即提交给服务器.当然,网络通信量也会增加.使用这个功能时要小心 ...