В статье kjellkod было указано, что если мы передадим ArrayList
в методе, который получает List
в качестве аргумента, тогда мы теряют производительность, поскольку ArrayList реализует дополнительный RandomAccess интерфейс.
Пример из статьи:
// SLOWER: as shown in http://ideone.com/1wnF1
private static void linearInsertion(Integer[] intArray, List<Integer> list) {
[...]
int list_size = list.size();
for (int i = 0; i < list_size; i++) {
if (integer.compareTo(list.get(i)) >= 0) { // ... more code
// FASTER: as shown in http://ideone.com/JOJ05
private static void linearInsertion(Integer[] intArray, ArrayList<Integer> list) {
[...]
int list_size = list.size();
for (int i = 0; i < list_size; i++) {
if (integer.compareTo(list.get(i)) >= 0) { // ... more code
Из справки:
Алгоритмы обобщенного списка рекомендуется проверять, соответствует ли данный список является экземпляром этого интерфейса перед применением алгоритма, который будет обеспечивать низкую производительность, если она будет применена к последовательному список доступа и изменить их поведение, если это необходимо, чтобы гарантировать приемлемая производительность.
Однако, если мы действительно передадим ArrayList в вышеуказанных методах и проверим list instanceof RandomAccess
, это будет верно в обоих случаях.
Итак, мой первый вопрос: , почему Java VM должна интерпретировать это как последовательный список в первом методе?
Я изменил тесты из статьи, чтобы проверить это поведение на моей машине. Когда тест выполняется на ideone, он показывает результаты, похожие на kjellkod's. Но когда я запускал его локально, я получил неожиданные результаты, которые противоречат объяснению статьи, а также моему пониманию. Похоже, что в моем случае ArrayList, как итерация List, на 5-25% быстрее, чем ссылка на ArrayList:
Как объяснить эту разницу? Зависит ли она от архитектуры или количества процессорных ядер? Моя рабочая конфигурация машины - Windows 7 Professional x64, Intel Core i5-3470 (4 ядра, 4 потока), 16 ГБ оперативной памяти.