请考虑以下代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class testSortingSpeed {
public static final int TOTAL_NUMBER = 10000000;
public static void main(String[] args) {
System.out.println("Creating ArrayList:");
List<Pair<Integer, Integer>> a = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < TOTAL_NUMBER; i++) {
Pair<Integer, Integer> p = new Pair<>(
(int ) Math.random() * TOTAL_NUMBER,
(int ) Math.random() * TOTAL_NUMBER);
a.add(p);
}
long end = System.currentTimeMillis();
System.out.println("Time Elapsed = " + ((end - start) / 1000.0) + " seconds");
System.out.println();
System.out.println("Creating LinkedList:");
List<Pair<Integer, Integer>> b = new LinkedList<>();
start = System.currentTimeMillis();
for (int i = 0; i < TOTAL_NUMBER; i++) {
Pair<Integer, Integer> p = new Pair<>(
(int ) Math.random() * TOTAL_NUMBER,
(int ) Math.random() * TOTAL_NUMBER);
b.add(p);
}
end = System.currentTimeMillis();
System.out.println("Time Elapsed = " + ((end - start) / 1000.0) + " seconds");
System.out.println();
System.out.println("Sorting ArrayList:");
start = System.currentTimeMillis();
Collections.sort(a, Pair.LEXICOGRAPHIC_ORDER);
end = System.currentTimeMillis();
System.out.println("Time Elapsed = " + ((end - start) / 1000.0) + " seconds");
System.out.println();
System.out.println("Sorting LinkedList:");
start = System.currentTimeMillis();
Collections.sort(b, Pair.LEXICOGRAPHIC_ORDER);
end = System.currentTimeMillis();
System.out.println("Time Elapsed = " + ((end - start) / 1000.0) + " seconds");
System.out.println();
}
}
其中Pair是自定义数据结构。
Pair<F, S> { F first; S second; }
上述程序的输出: 创建ArrayList: 经过的时间= 0.885秒
创建LinkedList: 经过的时间= 9.617秒
对ArrayList进行排序: 经过的时间= 0.128秒
排序LinkedList: 经过的时间= 0.351秒
我有点困惑,直觉上,LinkedList创建应该比ArrayList更好。
对于排序,这是预期的,正如在api中所说: https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html 那个Collections.sort 将列表转储到ArrayList,对其进行排序, 并将其转换回原始列表类型(不确定)
我想如果原始列表类型是ArrayList,可能会有优化。
答案 0 :(得分:0)
这将是特定于实现的,具体取决于ArrayList在您的平台上的增长方式......但在大多数平台上,每次达到容量时,它的大小都会增加1.5倍。
以下是JDK 1.8的代码:
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
如果你将一千万个对象添加到一个空的ArrayList中,这个方法将被调用36次,其默认初始容量为10.我已经对grow()和Arrays.copyOf()进行了一些分析,并且它们非常快,即使对于大型阵列也是如此。
另一方面,LinkedList需要为添加到其中的每个元素分配一个新的Node对象 - 一千万次。这就是为什么LinkedList在这种情况下更慢的原因。当您需要在列表的开头或中间附近插入或删除元素时,它会多。