我们在实现 List 时,通常会考虑使用 ArrayList 和 LinkedList ,Vector 属于遗留代码类库,已不推荐使用。
下面,我们将以 List 的各种常用操作作为测试指标,验证 ArrayList 和 LinkedList 两者的性能指标。
0.准备工作
在此之前,先定义好测试模板,更好的帮助我们编写测试代码;
ContainerTest 为一个通用的测试基类,用泛型来兼容 ArrayList 和 LinkedList;再定义抽象方法 test(),便于我们自定义各种需要测试的方法。
public abstract class ContainerTest<T extends List> {
private T list;
public abstract long test();
public ContainerTest(T list) {
this.list = list;
}
public T getList() {
return list;
}
public void setList(T list) {
this.list = list;
}
}
与此同时,拥有一个生成测试数据的工具类 InitIntegerList 也是相当的有必要;
public class InitIntegerList {
public static <T extends List> T initList(T list, int size) {
list.clear();
for (int i = 0; i < size; i++) {
list.add(i);
}
return list;
}
}
接下来,编写提供各种测试功能 ListPerformanceTest 工具类。其中 initList() 用于生成测试数据;displayHead() 打印测试信息的表头;
public class ListPerformanceTest {
public static <T extends List> T initList(T list, int size) {
List initList = InitIntegerList.initList(list, size);
list.addAll(initList);
return list;
}
public static <T> void displayHead(T t, String methodName) {
System.out.println(t.getClass().getSimpleName() + "\t" + methodName);
System.out.println("集合长度\t操作次数\t平均时间");
}
后续编写的方法都是在 ListPerformanceTest 内运行,重复的部分不再贴出来了。每次执行测试方法后,打印方法执行次数、集合长度、平均操作时间作为参考,在随机测试方面,指定 Random 随机种子,保证每次随机取得元素的一致性。
1.顺序添加
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void add(T list, int loops) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
for (int i = 0; i < loops; i++) {
t.add(i);
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(list.size() + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[] integers = {10000, 30000, 50000};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "顺序添加");
for (int i = 0; i < integers.length; i++) {
add(arrayList, integers[i]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "顺序添加");
for (int i = 0; i < integers.length; i++) {
add(linkedList, integers[i]);
}
}
ArrayList 顺序添加
集合长度 操作次数 平均时间
10000 10000 149
40000 30000 70
90000 50000 51
LinkedList 顺序添加
集合长度 操作次数 平均时间
10000 10000 60
40000 30000 31
90000 50000 27
2.中部添加
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void addHalf(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
for (int i = 0; i < loops; i++) {
t.add(size / 2, i);
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "中部添加");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
addHalf(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "中部添加");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
addHalf(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 中部添加
集合长度 操作次数 平均时间
10000 100 2061
30000 200 5779
50000 300 5098
LinkedList 中部添加
集合长度 操作次数 平均时间
10000 100 17215
30000 200 30818
50000 300 32258
3.头部添加
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void addHead(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
for (int i = 0; i < loops; i++) {
t.add(0, i);
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "头部添加");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
addHead(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "头部添加");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
addHead(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 头部添加
集合长度 操作次数 平均时间
10000 100 4900
30000 200 11711
50000 300 10227
LinkedList 头部添加
集合长度 操作次数 平均时间
10000 100 419
30000 200 517
50000 300 274
4.随机添加
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void addRandom(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
Random random = new Random(47);
long startTime = System.nanoTime();
T t = getList();
for (int i = 0; i < loops; i++) {
t.add(random.nextInt(size), i);
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "随机添加");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
addRandom(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "随机添加");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
addRandom(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 随机添加
集合长度 操作次数 平均时间
10000 100 3934
30000 200 6010
50000 300 6568
LinkedList 随机添加
集合长度 操作次数 平均时间
10000 100 12981
30000 200 15777
50000 300 17045
5.迭代遍历
/**
*
* @param list 测试容器
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void iter(T list, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
ListIterator listIterator = t.listIterator();
while (listIterator.hasNext()) {
listIterator.next();
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / size;
System.out.println(size + "\t" + size + "\t" + avg);
}
public static void main(String[] args) {
Integer[] integers = {10000, 30000, 50000};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "迭代遍历");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(arrayList, integers[i]);
iter(arrayList, integers[i]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "迭代遍历");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(linkedList, integers[i]);
iter(linkedList, integers[i]);
}
}
ArrayList 迭代遍历
集合长度 操作次数 平均时间
10000 10000 108
30000 30000 57
50000 50000 37
LinkedList 迭代遍历
集合长度 操作次数 平均时间
10000 10000 72
30000 30000 11
50000 50000 12
6.随机访问
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void get(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
Random random = new Random(47);
for (int i = 0; i < loops; i++) {
t.get(random.nextInt(size));
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "随机访问");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
get(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "随机访问");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
get(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 随机访问
集合长度 操作次数 平均时间
10000 100 3327
30000 200 494
50000 300 98
LinkedList 随机访问
集合长度 操作次数 平均时间
10000 100 13331
30000 200 18803
50000 300 16241
7.随机更新
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void set(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
Random random = new Random(47);
for (int i = 0; i < loops; i++) {
t.set(random.nextInt(size), i);
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "随机更新");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
set(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "随机更新");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
set(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 随机更新
集合长度 操作次数 平均时间
10000 100 4996
30000 200 538
50000 300 197
LinkedList 随机更新
集合长度 操作次数 平均时间
10000 100 14090
30000 200 15057
50000 300 16582
8.随机移除
/**
*
* @param list 测试容器
* @param loops 循环次数
* @param size 集合长度
* @param <T> 指定继承自 List 的泛型
*/
public static <T extends List> void remove(T list, int loops, int size) {
ContainerTest<T> testList = new ContainerTest<T>(list) {
@Override
public long test() {
long startTime = System.nanoTime();
T t = getList();
Random random = new Random(47);
for (int i = 0; i < loops; i++) {
t.remove(random.nextInt(size - loops));
}
return System.nanoTime() - startTime;
}
};
long operateTime = testList.test();
long avg = operateTime / loops;
System.out.println(size + "\t" + loops + "\t" + avg);
}
public static void main(String[] args) {
Integer[][] integers = {{100, 10000}, {200, 30000}, {300, 50000}};
ArrayList<Integer> arrayList = new ArrayList<>();
displayHead(arrayList, "随机移除");
for (int i = 0; i < integers.length; i++) {
arrayList = initList(new ArrayList(), integers[i][1]);
remove(arrayList, integers[i][0], integers[i][1]);
}
System.out.println();
LinkedList<Integer> linkedList = new LinkedList<>();
displayHead(linkedList, "随机移除");
for (int i = 0; i < integers.length; i++) {
linkedList = initList(new LinkedList(), integers[i][1]);
remove(linkedList, integers[i][0], integers[i][1]);
}
}
ArrayList 随机移除
集合长度 操作次数 平均时间
10000 100 6140
30000 200 6284
50000 300 6349
LinkedList 随机移除
集合长度 操作次数 平均时间
10000 100 11941
30000 200 20445
50000 300 16182
9.测试结果汇总
测试项目 | ArrayList | LinkedList |
---|---|---|
顺序添加 | 低 | 高 |
中部添加 | 高 | 低 |
头部添加 | 低 | 高 |
随机添加 | 高 | 低 |
迭代遍历 | 低 | 高 |
随机访问 | 高 | 低 |
随机更新 | 高 | 低 |
随机移除 | 高 | 低 |
ArrayList 底层为数组结构,故其随机访问性能高;LinkedList 为双向链表结构,拥有良好的伸缩拓展性,当在遍历和向首尾两端拓展时,性能优于 ArrayList 。
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!