集合(list)与数组的区别:
1.集合长度不固定,数组长度固定;换句话说,集合是动态的,数组是静态的。(重点)
2.集合可以指定下标索引,并且会自动给插入位置向后挪位置,而不是像数组那样覆盖。
按照ArraryList 和 LinkedList特性,,,发现ArraryList 以数组数据结构方式保存,LinkedList以数据链表方式保存、。。。上面的场景遇到问题了,既要add也需要get,这样的话,哪个都不适合了。。。
现在如何抉择使用哪个呢? (先提出问题,后面有答案)
遇到这样的问题,我就想到掌握的这些概念都是出于理论层面,没有从实际代码性能中查看,到底差距有多大,下面就已实际代码性能上面分析问题,然后看看add的性能差距多大,get的性能差距多大,然后作为我们选择使用的一个参考。。。
ArrayList是动态扩展的数组,LinkedList是双向链表的数据结构。
所以大多数人持有这样观点:
AL易于查找;有频繁的插入、删除使用AL不合适,因涉及到其他元素左右移动问题;
LL不易于查找;有频繁的插入、删除操作使用LL比较合适,因只涉及修改前后连接;
这里先不对以上观点给出我的结论,也没有非常仔细跟踪过java源码。这里给出一个测试样例及测试结果。测试结果的结论似乎不支持以上说法。当然,可能有涉及到测试样例的合理性、数据量是否足够大的问题,但个人认为这个例子还是合理的。大家有疑问的可以提出。欢迎大家多多交流。
- @SuppressWarnings("all")
- static final class ArrayListAndLinkedArrayList{
- static final int N=100000;
- static long timeList(List list){
- long start=System.currentTimeMillis();
- Object o = new Object();
- for(int i=0;i<N;i++) {
- int id = (int) new java.util.Random().nextInt((i==0)?(i+1):i);
- // System.out.println(id);
- list.add(id, o);
- }
- return System.currentTimeMillis()-start;
- }
- static long readList(List list){
- long start=System.currentTimeMillis();
- for(int i=0,j=list.size();i<j;i++){
- int id = (int) new java.util.Random().nextInt((i==0)?(i+1):i);
- list.get(id);
- }
- return System.currentTimeMillis()-start;
- }
- static List addList(List list){
- Object o = new Object();
- for(int i=0;i<N;i++) {
- int id = (int) new java.util.Random().nextInt((i==0)?(i+1):i);
- list.add(id, o);
- }
- return list;
- }
- static long removeList(List list){
- list=addList(list);
- long start=System.currentTimeMillis();
- for(int i=0;i<N;i++) {
- int id = (int) new java.util.Random().nextInt((N-i)==0?(1):N-i);
- list.remove(id);
- }
- return System.currentTimeMillis()-start;
- }
- public static void main(String[] args) {
- System.out.println("ArrayList添加"+N+"条耗时:"+timeList(new ArrayList()));
- System.out.println("LinkedList添加"+N+"条耗时:"+timeList(new LinkedList()));
- List list1=addList(new ArrayList<>());
- List list2=addList(new LinkedList<>());
- System.out.println("ArrayList查找"+N+"条耗时:"+readList(list1));
- System.out.println("LinkedList查找"+N+"条耗时:"+readList(list2));
- System.out.println("ArrayList删除"+N+"条耗时:"+removeList(new ArrayList()));
- System.out.println("LinkedList删除"+N+"条耗时:"+removeList(new LinkedList()));
- }
- }
- 100000条
- ArrayList添加100000条耗时:1719
- LinkedList添加100000条耗时:56433
- ArrayList查找100000条耗时:22
- LinkedList查找100000条耗时:4968
- ArrayList删除100000条耗时:641
- LinkedList删除100000条耗时:57121
- 5000条
- ArrayList添加5000条耗时:25
- LinkedList添加5000条耗时:77
- ArrayList查找5000条耗时:5
- LinkedList查找5000条耗时:136
- ArrayList删除5000条耗时:13
- LinkedList删除5000条耗时:62
当然,这里random会耗费一些时间,但这对两者是相等的,所以可以忽略。
以上的测试结果,似乎总是支持AL比LL的各方面都要好。
所以在这里大家可以探讨下这个问题:
是
AL易于查找;有频繁的插入、删除使用AL不合适,因涉及到其他元素左右移动问题;
LL不易于查找;有频繁的插入、删除操作使用LL比较合适,因只涉及修改前后连接;
还是AL比LL的各方面都要好。