A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 胡文彬 中级黑马   /  2014-3-15 16:40  /  1818 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我看了很多资料或者博客,他们都提到了Arraylist查询遍历的时候,比LinkedList性能高,而在插入和删除的时候,Linkedlist又比arraylist性能高。
我想问一下具体的原因,他们的底层是怎么实现的?
难道仅仅是因为一个是数组,一个是链表吗?
希望大牛们能给我点建议。谢谢

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

6 个回复

倒序浏览
C:\Users\Admin\Desktop我不是大牛,但是可以给你说一下我的理解。
Arraylist是的底层是数组结构的,所以每一个元素对应的都有角标,我们查询的时候只通过角标就可以查询。但是你要删除某个元素的时候,这个元素后面的元素就必须向前移一位。当Arraylist的数据量很大的时候,这会需要很大的运算量,添加也是同样的道理,所以插入和删除的时候效率低。
Linkedlist是双链表结构的,它的特点是每一个元素都只会记得前边和后边的元素,所以在查询的时候它是按照从前的顺序一个个查的,但是删除的时候我们只需要把删除元素前后的元素互相记着对方即可。添加也是同样的道理。所以插入和删除效率高,查询低。
请看下面毕老师曾经画的图




评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
就是因为数组和链表的数据结构不同导致的啊 数组有角标查询什么的很快,但是要插入的话你得把后面的元素都移动,这样花费的时间就多了,而链表的话查询要从头节点逐个往下查 而插入的话只需要将插入位置前后两个元素的指针移动一下就好了 这样当然快了

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
小程序测试Arraylist和LinkedList的效率比较:
  1. public static void main(String[] args) {
  2.         List<String> arrayList = new ArrayList<String>();
  3.         List<String> linkedList = new LinkedList<String>();
  4.         long time1 = System.currentTimeMillis();
  5.         for(int i = 0; i < 1000000; i++) {
  6.             arrayList.add(new String("abc"));
  7.         }
  8.         long time2 = System.currentTimeMillis();
  9.         for(int i = 0; i < 1000000; i++) {
  10.             linkedList.add(new String("abc"));
  11.         }
  12.         long time3 = System.currentTimeMillis();
  13.         System.out.println("arrayList.insert_time = " + (time2 - time1));
  14.         System.out.println("linkedList.insert_time = " + (time3 - time2));
  15.         long time11 = System.currentTimeMillis();
  16.         for(int i = 0; i < 10000; i++) {
  17.             int random = RandomUtils.nextInt(10000);
  18.             String temp = arrayList.get(random);
  19.         }
  20.         long time12 = System.currentTimeMillis();
  21.         for(int i = 0; i < 10000; i++) {
  22.             int random = RandomUtils.nextInt(10000);
  23.             String temp = linkedList.get(random);
  24.         }
  25.         long time13 = System.currentTimeMillis();
  26.         System.out.println("arrayList.read_time = " + (time12 - time11));
  27.         System.out.println("linkedList.read_time = " + (time13 - time12));
  28.     }
复制代码

ArrayList 的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。 LinkedList 的查询效率低,但是增删效率很高。适用于增删动作的比较频繁,查询次数较少的元素管理集合。

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
有于ArrayList底层是链表,链表就是有指针作为连接的,也就是一个元素包含  元素 与 指针两部分,指针指向下一个元素的地址,就删除而言,你只需找到要删除的值,然后把与之相关的指针的值付给前一个值得与之相关的指针,就完成了删除
如果是数组你需要遍历数组,然后找到要删除的值如果该值后面有元素,你需要把后面的值都向前移动,如果元素很多就会浪费很多时间,所以效率就有点低了

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
Java 提供了两个类 ArrayList 和 LinkedList , ArrayList 的内部实现是基于内部数组 Object[] ,所以从概念上讲,它更像数组,但 LinkedList 的内部实现是基于一组连接的记录,所以,它更像一个链表结构,所以,它们在性能上有很大的差别。
在 ArrayList 的前面或中间插入数据时,必须将其后的所有数据相应的后移,这样必然要花费较多时间,所以,当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用 ArrayList 会提供比较好的性能;
而访问链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用 LinkedList 了。
如果在编程中,两种情形交替出现,这时,可以考虑使用 List 这样的通用接口,而不用关心具体的实现,在具体的情形下,它的性能由具体的实现来保证。
案例: LinkedList 实现堆栈
案例说明
ArrayList 的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。 LinkedList 的查询效率低,但是增删效率很高。适用于增删动作的比较频繁,查询次数较少的元素管理集合。
ArrayList , LinkedList 都是线程不安全的。
实现堆栈 1 )数组( ArrayList ,增删效率比较低,不适合)
        2 ) LinkedList (实现堆栈的好方法)
        3 ) java.util.Stack 类, Stack 是 Vector 的子类, Vector 类是一个线程安全的(是一个重量级的类),并继承了 Vector 的方法, Verctor 类和 ArrayList 的功能近乎相同。(不推荐使用 Stack 类来实现堆栈)。

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
1:事先能预知元素数量时,应优先选择 ArrayList,并且在构造中进行初始化
2:事先不能预知元素数量时,根据不同的迭代需要选择 ArrayList 或者 LinkedList
3:如果有很多的 remove 操作时,应优先选择 LinkedList
4:需要顺序迭代,也就是从第一个元素开始一个一个地访问到最后一个时,应优先选择 LinkedList
5:需要随机访问,也就是使用 get(int) 方法取任意下标访问时,应优先选择 ArrayList

评分

参与人数 1技术分 +1 收起 理由
zzkang0206 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马