ArrayList与LinkedList性能分析

书欣 Java经验 发布时间:2023-07-07 16:07:35 阅读数:4906 1
今天面试时,遇到一个问题“Arraylist和LinkedList的区别”
当然咯,笔者将按照常规回答,描述了ArrayList和LinkedList的区别,如下所示
ArrayList底层是数组,增删慢,查找快。
LinkedList底层是双向链表,增删快,查找慢
=================================================
下面笔者还将详细对"ArrayList与LinkedList性能"进行对比分析,如下所示

数据插入分析

1.头部插入法

package com.java265.test.list.add;
import com.java265.test.list.AddListUtil;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
 
public class HeaderAdd {
    public static void main(String[] args) {
        System.out.println("----------10w----------");
        useTime(100000);
        System.out.println("----------30w----------");
        useTime(300000);
        System.out.println("----------50w----------");
        useTime(500000);
        System.out.println("----------100w----------");
        useTime(1000000);

    }

    public static void useTime(int count){
        System.out.println
		("从ArrayList的头部新增耗时:" + addHeader(new ArrayList<>(), count) + "ms");
        System.out.println
		("从LinkedList的头部新增耗时:" + addHeader(new LinkedList<>(), count) + "ms");
    }

    /**
     * 从List的头部新增元素
     * @param list list
     * @param count 新增元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static long addHeader(List<String> list, int count) {
       long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            list.add(0, "onemore-" + i);
        }
        long end =  System.currentTimeMillis();
        return (end - start);
    }
}
数据统计:数据量/w , 耗时/ms

----------11w----------
从ArrayList的头部新增耗时:510ms
从LinkedList的头部新增耗时:20ms
----------31w----------
从ArrayList的头部新增耗时:3982ms
从LinkedList的头部新增耗时:27ms
----------51w----------
从ArrayList的头部新增耗时:12019ms
从LinkedList的头部新增耗时:19ms
----------101w----------
从ArrayList的头部新增耗时:56105ms
从LinkedList的头部新增耗时:580ms 
数量级(万) ArrayList LinkedList
11 510 ms 20ms
31 3982 ms 27 ms
51 12019 ms 19 ms
101 56105 ms 580 ms
从实验结果上,我们可以看出
     头部插入法LinkedList效率远高于ArrayList

2.尾部插入法

package com.java265.test.list.add;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

package com.java265.test.list.add;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
 
public class TailAdd {
    public static void main(String[] args) {
        System.out.println("----------1w----------");
        useTime(10000);
        System.out.println("----------5w----------");
        useTime(50000);
        System.out.println("----------10w----------");
        useTime(100000);
        System.out.println("----------15w----------");
        useTime(150000);
        System.out.println("----------20w----------");
        useTime(200000);
        System.out.println("----------30w----------");
        useTime(300000);
        System.out.println("----------50w----------");
        useTime(500000);
        System.out.println("----------70w----------");
        useTime(700000);
        System.out.println("----------100w----------");
        useTime(1000000);
    }

    public static void useTime(int count){
        System.out.println
		("从ArrayList的尾部新增耗时:" + addTail(new ArrayList<>(), count) + "ms");
        System.out.println
		("从LinkedList的尾部新增耗时:" + addTail(new LinkedList<>(), count) + "ms");
    }

    /**
     * 从List的尾部新增元素
     * @param list list
     * @param count 新增元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static long addTail(List<String> list, int count) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            list.add("tail-" + i);
        }
        long end = System.currentTimeMillis();
        return (end - start);
    }
}

//运行以上代码,将输出以下信息
----------1w----------
从ArrayList的尾部新增耗时:5ms
从LinkedList的尾部新增耗时:4ms
----------5w----------
从ArrayList的尾部新增耗时:10ms
从LinkedList的尾部新增耗时:4ms
----------10w----------
从ArrayList的尾部新增耗时:15ms
从LinkedList的尾部新增耗时:4ms
----------15w----------
从ArrayList的尾部新增耗时:5ms
从LinkedList的尾部新增耗时:23ms
----------20w----------
从ArrayList的尾部新增耗时:7ms
从LinkedList的尾部新增耗时:9ms
----------30w----------
从ArrayList的尾部新增耗时:11ms
从LinkedList的尾部新增耗时:27ms
----------50w----------
从ArrayList的尾部新增耗时:13ms
从LinkedList的尾部新增耗时:68ms
----------70w----------
从ArrayList的尾部新增耗时:23ms
从LinkedList的尾部新增耗时:379ms
----------100w----------
从ArrayList的尾部新增耗时:48ms
从LinkedList的尾部新增耗时:120ms
从实验结果上,我们可以看出从数据测试来看
   对于尾插法而言
     不是说ArrayList就一定比LinkedList效率高
	  经过大量的数据测试,
	 发现10w以内LinkedList比ArrayList快
	     100w以上ArrayList明显比LinkedList快

2.数据删除

1.头部删除法

package com.java265.test.list.del;

import com.java265.test.list.DeleteListUtil;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
 
public class DelList {

    public static void main(String[] args) {
        System.out.println("----------1w----------");
        delToList(10000);
        System.out.println("----------5w----------");
        delToList(50000);
        System.out.println("----------10w----------");
        delToList(100000);
        System.out.println("----------15w----------");
        delToList(150000);
        System.out.println("----------20w----------");
        delToList(200000);
        System.out.println("----------30w----------");
        delToList(300000);
        System.out.println("----------50w----------");
        delToList(500000);
        System.out.println("----------70w----------");
        delToList(700000);
        System.out.println("----------100w----------");
        delToList(1000000);

    }

    public static void delToList(int count){

        System.out.println
		("从ArrayList的头部删除元素:" + deleteHeader(new ArrayList<>(), count) + "ms");
        System.out.println
		("从LinkedList的头部删除元素:" + deleteHeader(new LinkedList<>(), count) + "ms");

    }

    /**
     * 从List的头部删除元素
     * @param list list
     * @param count 删除元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static double deleteHeader(List<String> list, int count) {
        for (int i = 0; i < count; i++) {
            list.add("del-" + i);
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            list.remove(0);
        }
        long end = System.currentTimeMillis();
        return (end - start);
    }

}

 //以上代码运行,将输出以下信息
----------1w----------
从ArrayList的头部删除元素:6.0ms
从LinkedList的头部删除元素:1.0ms
----------5w----------
从ArrayList的头部删除元素:79.0ms
从LinkedList的头部删除元素:2.0ms
----------10w----------
从ArrayList的头部删除元素:416.0ms
从LinkedList的头部删除元素:4.0ms
----------15w----------
从ArrayList的头部删除元素:875.0ms
从LinkedList的头部删除元素:2.0ms
----------20w----------
从ArrayList的头部删除元素:1587.0ms
从LinkedList的头部删除元素:5.0ms
----------30w----------
从ArrayList的头部删除元素:3623.0ms
从LinkedList的头部删除元素:6.0ms
----------50w----------
从ArrayList的头部删除元素:11891.0ms
从LinkedList的头部删除元素:8.0ms
----------70w----------
从ArrayList的头部删除元素:26807.0ms
从LinkedList的头部删除元素:15.0ms
----------100w----------
从ArrayList的头部删除元素:56940.0ms
从LinkedList的头部删除元素:30.0ms

从实验结果上,我们可以看出
  头部删除LinkedList比ArrayList快

2.尾部删除法

package com.java265.test.list.del;

import com.java265.test.list.DeleteListUtil;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class DelList {
    public static void main(String[] args) {
        System.out.println("----------1w----------");
        delToList(10000);
        System.out.println("----------5w----------");
        delToList(50000);
        System.out.println("----------10w----------");
        delToList(100000);
        System.out.println("----------15w----------");
        delToList(150000);
        System.out.println("----------20w----------");
        delToList(200000);
        System.out.println("----------30w----------");
        delToList(300000);
        System.out.println("----------50w----------");
        delToList(500000);
        System.out.println("----------70w----------");
        delToList(700000);
        System.out.println("----------100w----------");
        delToList(1000000);

    }

    public static void delToList(int count){

        System.out.println
		("从ArrayList的尾部删除元素:" + deleteTail(new ArrayList<>(), count) + "ms");
        System.out.println
		("从LinkedList的尾部删除元素:" + deleteTail(new LinkedList<>(), count) + "ms");

    }

    /**
     * 从List的尾部删除元素
     * @param list list
     * @param count 删除元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static double deleteTail(List<String> list, int count) {
        for (int i = 0; i < count; i++) {
            list.add("del-" + i);
        }
        long start = System.currentTimeMillis();;
        for (int i = 0; i < count; i++) {
            list.remove(list.size() - 1);
        }
        long end = System.currentTimeMillis();;
        return (end - start);
    }
}
 
//运行以上代码,将输出以下信息
----------1w----------
从ArrayList的尾部删除元素:1.0ms
从LinkedList的尾部删除元素:2.0ms
----------5w----------
从ArrayList的尾部删除元素:1.0ms
从LinkedList的尾部删除元素:8.0ms
----------10w----------
从ArrayList的尾部删除元素:0.0ms
从LinkedList的尾部删除元素:6.0ms
----------15w----------
从ArrayList的尾部删除元素:1.0ms
从LinkedList的尾部删除元素:4.0ms
----------20w----------
从ArrayList的尾部删除元素:0.0ms
从LinkedList的尾部删除元素:4.0ms
----------30w----------
从ArrayList的尾部删除元素:1.0ms
从LinkedList的尾部删除元素:14.0ms
----------50w----------
从ArrayList的尾部删除元素:1.0ms
从LinkedList的尾部删除元素:57.0ms
----------70w----------
从ArrayList的尾部删除元素:2.0ms
从LinkedList的尾部删除元素:29.0ms
----------100w----------
从ArrayList的尾部删除元素:4.0ms
从LinkedList的尾部删除元素:27.0ms
从实验结果上,我们可以看出
   尾部删除ArrayList比LinkedList快

3.数据检索

1.for循环遍历List

package com.java265.test.list.query;

import com.java265.test.list.IterationListUtil;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class QueryList {
    public static void main(String[] args) {
        System.out.println("----------1w----------");
        IteratToList(10000);
        System.out.println("----------5w----------");
        IteratToList(50000);
        System.out.println("----------10w----------");
        IteratToList(100000);
        System.out.println("----------15w----------");
        IteratToList(150000);
    }

    public static void IteratToList(int count){

        System.out.println
		("通过for循环遍历ArrayList:" + getByFor(new ArrayList<>(count), count) + "ms");
        System.out.println
		("通过for循环遍历LinkedList:" + getByFor(new LinkedList<>(), count) + "ms");

    }

    /**
     * 通过for循环遍历List
     *
     * @param list  list
     * @param count 遍历元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static double getByFor(List<String> list, int count) {
        for (int i = 0; i < count; i++) {
            list.add("for-" + i);
        }
        String name = "本草中国";
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            if (name.equals(list.get(i))) {
                System.out.println(name);
            }
        }
        long end = System.currentTimeMillis();
        return (end - start);
    }
}
 

//运行以上代码,将输出以下信息

----------1w----------
通过for循环遍历ArrayList:1.0ms
通过for循环遍历LinkedList:43.0ms
----------5w----------
通过for循环遍历ArrayList:1.0ms
通过for循环遍历LinkedList:1924.0ms
----------10w----------
通过for循环遍历ArrayList:1.0ms
通过for循环遍历LinkedList:11731.0ms
----------15w----------
通过for循环遍历ArrayList:1.0ms
通过for循环遍历LinkedList:13699.0ms
从实验结果上,我们可以看出
    使用for循环遍历时
	ArrayList的效率高于LinkedList,而且LinkedList的效率极低。

2.foreach循环遍历List

package com.java265.test.list.query;

import com.java265.test.list.IterationListUtil;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
 
public class QueryList {
    public static void main(String[] args) {
        System.out.println("----------1w----------");
        IteratToList(10000);
        System.out.println("----------5w----------");
        IteratToList(50000);
        System.out.println("----------10w----------");
        IteratToList(100000);
        System.out.println("----------50w----------");
        IteratToList(500000);
        System.out.println("----------100w----------");
        IteratToList(1000000);
    }

    public static void IteratToList(int count){

        System.out.println
		("通过foreach遍历ArrayList:" + getByForeach(new ArrayList<>(count), count) + "ms");
        System.out.println
		("通过foreach遍历LinkedList:" + getByForeach(new LinkedList<>(), count) + "ms");
    }

    /**
     * 通过foreach遍历List
     *
     * @param list  list
     * @param count 遍历元素的个数
     * @return 所耗费的时间(单位:ms)
     */
    public static double getByForeach(List<String> list, int count) {
        for (int i = 0; i < count; i++) {
            list.add("foreach-" + i);
        }
        String name = "本草中国";
        long start = System.currentTimeMillis();
        for (String str : list) {
            if (name.equals(str)) {
                System.out.println(name);
            }
        }
        long end = System.currentTimeMillis();
        return (end - start);
    }
}

//运行以上代码,将输出以下信息
----------1w----------
通过foreach遍历ArrayList:2.0ms
通过foreach遍历LinkedList:2.0ms
----------5w----------
通过foreach遍历ArrayList:1.0ms
通过foreach遍历LinkedList:5.0ms
----------10w----------
通过foreach遍历ArrayList:2.0ms
通过foreach遍历LinkedList:10.0ms
----------50w----------
通过foreach遍历ArrayList:4.0ms
通过foreach遍历LinkedList:7.0ms
----------100w----------
通过foreach遍历ArrayList:5.0ms
通过foreach遍历LinkedList:9.0ms
从实验结果上,我们可以看出
    使用foreach遍历时
	 ArrayList的效率和LinkedList相差不大。

从以上的测试情况,我们可以得出以下结论
ArrayList是实现基于动态数组的数据结构
LinkedList基于链表的数据结构

新增元素:
  头插法:
    LinkedList效率远高于ArrayList
  尾插法:
   对于尾插法而言,
       ArrayList就一定比LinkedList效率高
	   经测试
         10w以内LinkedList比ArrayList快
		 100w以上ArrayList明显比LinkedList

删除元素
  头部删除:
    头部删除LinkedList比ArrayList快
  尾部删除:
    尾部删除ArrayList比LinkedList快
 
数据查询
  使用for循环遍历时
   ArrayList的效率高于LinkedList
    而
   LinkedList的效率极低
  
  使用foreach遍历时
    ArrayList的效率和LinkedList相差不大
	   所以需避免使用for循环遍历LinkedList集合
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202307/16887172857029.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者