1、ArrayList通过数组实现,是一片连续的内存区域,可以用下标直接定位到内存地址,查询效率高;因为插入和删除需要移动内存块,插入和删除元素效率低。
2、LinkedList通过链表实现,元素之间直接通过指针相互关联,查询需要遍历链表,效率较低;插入和删除只需要改变指针指向,插入和删除效率高。
下面来验证一下上述内容,先说一下结论:
并不是所有的删除和插入操作LinkedList都比ArrayList快!
我们将删除和插入分为几种情况来验证
头部插入(删除)、中部插入(删除)、尾部插入(删除)
查询
public static void main(String[] args) {
/*LinkedList*/
List<String> linkedList = new LinkedList<>();
for (int i=0;i<=10000000;i++){
linkedList.add("linked");
}
Long startTime = System.currentTimeMillis();
linkedList.get(4678645);
System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms");
/*ArrayList*/
List<String> arrayList = new ArrayList<>();
for (int i=0;i<=10000000;i++){
arrayList.add("array");
}
Long startTime1 = System.currentTimeMillis();
arrayList.get(4678645);
System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms");}
LinkedList耗时:27ms
ArrayList耗时:0ms
LinkedList和ArrayList在一千万个元素中随机查询,可以看到ArrayList相对LinkedList快很多。
头部删除
public static void main(String[] args) {
/*LinkedList*/
List<String> linkedList = new LinkedList<>();
for (int i=0;i<=10000000;i++){
linkedList.add("linked");
}
Long startTime = System.currentTimeMillis();
linkedList.remove(0);
System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms");/*ArrayList*/
List<String> arrayList = new ArrayList<>();
for (int i=0;i<=10000000;i++){
arrayList.add("array");
}
Long startTime1 = System.currentTimeMillis();
arrayList.remove(0);
System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms");}
LinkedList耗时:0ms
ArrayList耗时:4ms
在头部删除,LinkedList要比ArrayList快。因为ArrayList在删除后有近一千万个元素要移动;而LinkedList只需要将头部的指针删除即可。
中部删除
public static void main(String[] args) { /*LinkedList*/ List<String> linkedList = new LinkedList<>(); for (int i=0;i<=10000000;i++){ linkedList.add("linked"); } Long startTime = System.currentTimeMillis(); linkedList.remove(5000000); System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms"); /*ArrayList*/ List<String> arrayList = new ArrayList<>(); for (int i=0;i<=10000000;i++){ arrayList.add("array"); } Long startTime1 = System.currentTimeMillis(); arrayList.remove(5000000); System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms"); }
LinkedList耗时:14ms
ArrayList耗时:1ms
在中部删除, LinkedList反而要比ArrayList要慢,是因为LinkedList遍历五百万的元素比ArrayList移动五百万的元素还要慢。
尾部删除
public static void main(String[] args) { /*LinkedList*/ List<String> linkedList = new LinkedList<>(); for (int i=0;i<=10000000;i++){ linkedList.add("linked"); } Long startTime = System.currentTimeMillis(); linkedList.remove(9999999); System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms"); /*ArrayList*/ List<String> arrayList = new ArrayList<>(); for (int i=0;i<=10000000;i++){ arrayList.add("array"); } Long startTime1 = System.currentTimeMillis(); arrayList.remove(9999999); System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms"); }
LinkedList耗时:0ms
ArrayList耗时:0ms
在尾部删除,ArrayList不需要移动元素,LinkedList只需要删除尾部指针,因此两者耗时相近。
头部插入
public static void main(String[] args) { /*LinkedList*/ List<String> linkedList = new LinkedList<>(); for (int i=0;i<=10000000;i++){ linkedList.add("linked"); } Long startTime = System.currentTimeMillis(); linkedList.add(0,"123"); System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms"); /*ArrayList*/ List<String> arrayList = new ArrayList<>(); for (int i=0;i<=10000000;i++){ arrayList.add("array"); } Long startTime1 = System.currentTimeMillis(); arrayList.add(0,"123"); System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms"); }
LinkedList耗时:0ms
ArrayList耗时:7ms
头部插入与头部删除一样,ArrayList同样需要移动近一千万的元素,而LinkedList只需要删除头部的指针即可。LinkedList比ArrayList快。
中部插入
public static void main(String[] args) { /*LinkedList*/ List<String> linkedList = new LinkedList<>(); for (int i=0;i<=10000000;i++){ linkedList.add("linked"); } Long startTime = System.currentTimeMillis(); linkedList.add(5000000,"123"); System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms"); /*ArrayList*/ List<String> arrayList = new ArrayList<>(); for (int i=0;i<=10000000;i++){ arrayList.add("array"); } Long startTime1 = System.currentTimeMillis(); arrayList.add(5000000,"123"); System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms"); }
LinkedList耗时:14ms
ArrayList耗时:3ms
在中部插入与删除类似,LinkedList的遍历速度没有ArrayList移动元素的速度快。ArrayList比LinkedList快。
尾部插入
public static void main(String[] args) { /*LinkedList*/ List<String> linkedList = new LinkedList<>(); for (int i=0;i<=10000000;i++){ linkedList.add("linked"); } Long startTime = System.currentTimeMillis(); linkedList.add("123"); System.out.println("LinkedList耗时:" + (System.currentTimeMillis()-startTime) + "ms"); /*ArrayList*/ List<String> arrayList = new ArrayList<>(); for (int i=0;i<=10000000;i++){ arrayList.add("array"); } Long startTime1 = System.currentTimeMillis(); arrayList.add("123"); System.out.println("ArrayList耗时:" + (System.currentTimeMillis()-startTime1) + "ms"); }
LinkedList耗时:0ms
ArrayList耗时:0ms
尾部插入与尾部删除类似,LinkedList不需要遍历,ArrayList不需要移动元素,因此两者效率相近。
通过以上验证可知:
并不是所有的插入、删除,LinkedList都要比ArrayList快,要看数据量,要根据具体插入、删除的位置而定。