问题
Consider the following code:
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();
}
}
where Pair is a custom defined data structure.
Pair<F, S> { F first; S second; }
The output of the above program: Creating ArrayList: Time Elapsed = 0.885 seconds
Creating LinkedList: Time Elapsed = 9.617 seconds
Sorting ArrayList: Time Elapsed = 0.128 seconds
Sorting LinkedList: Time Elapsed = 0.351 seconds
I am a bit baffled, cos intuitively, LinkedList creation should be better than ArrayList.
For sorting, that's kinda expected, as it says in api: https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html that Collections.sort dumps the list to an ArrayList, sort it, and convert it back to original list type (not sure about this)
and I guess there is probably optimization if the original list type is ArrayList.
回答1:
This will be implementation specific, depending on how ArrayList grows on your platform... But on most platforms, it multiplies its size by a factor of 1.5 every time it's capacity is reached.
Here's the code from 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);
}
This method will be called 36 times if you're adding ten million objects into an empty ArrayList, which has a default initial capacity of 10. I've done some profiling on grow() and Arrays.copyOf(), and they're very fast, even for large arrays.
LinkedList, on the other hand, needs to allocate a new Node object for every element added to it--ten million times. That's why LinkedList is slower in this case. It's much faster when you need to insert or remove elements somewhere near the beginning or middle of the list.
来源:https://stackoverflow.com/questions/29584600/performance-on-java-arraylist-vs-linkedlist-pertaining-to-only-creation-inserti