Страницы

Поиск по вопросам

понедельник, 10 декабря 2018 г.

Что работает быстрее: массив или ArrayList?

Что работает быстрее? Прогнал тест 100 раз. Результаты всегда разные: то один быстрее, то второй. Так есть ли реальный выигрыш в использовании массива вместо ArrayList? ArrayList создавал с нужным размером сразу, чтобы время на "расширение" не тратилось. Проверялось быстродействие команды add. Пытался понять, уменьшит ли замена ArrayList на обычный массив в "узких местах" время выполнения (часто слышал такое предположение). Если в моем случае всегда известен заранее размер массива/листа. Результаты получились случайные. Иногда ArrayList значительно быстрее, иногда массив, иногда они равны. import java.util.*;
public class Main { private static int COUNT = 1000000;
private static double getPeriod(Runnable r) { System.gc(); Date date = new Date(); r.run(); return (new Date().getTime() - date.getTime()); }
private static void testList(final List list) { double period = getPeriod(new Runnable() { public void run() { for (int i = 0; i < COUNT; i++) { list.add(new Object()); } } }); System.out.println("List " + period); }
private static void testArray(final Object[] array) { double period = getPeriod(new Runnable() { public void run() { for (int i = 0; i < COUNT; i++) { array[i] = new Object(); } } }); System.out.println("Array " + period); }
public static void main(String[] args) { for (int i = 0; i < 100; i++) { List arrayList = new ArrayList(COUNT); Object[] array = new Object[COUNT];
testList(arrayList); testArray(array); } } }


Ответ

Обычный массив почти наверняка будет выигрывать в скорости как при доступе, так и при записи. Хотя бы потому, что при обращении к ArrayList у вас лишний вызов метода, а может и не один. С другой стороны, внутри ArrayList'а тот же самый массив и доступ вполняется по тому же принципу, поэтому если нет чрезмерной нагрузки на него, то в общем их производительность примерно одного порядка. Разница для вас в том, что с листами работать намного проще и удобнее, чем с массивами. По этой причине вам не следует заниматься ерундой и гонять какие-то нелепые тесты, а просто использовать ArrayList, если только у вас нет каких-то ОЧЕНЬ серьёзных оснований использовать массив. Одно из таких оснований: вы точно знаете заранее размер массива и вы точно знаете, что использование этого массива в коде ограничено и вам не придётся городить огород, чтобы гонять потом эти массивы в листы и наоборот. UPD Что за числа в вашем тесте детские? 1000.000? Это просто смешно. Я прогнал тест на выполнение 10.000.000.000 добавлений и получил вот что: primitive array: 78896 ms array list: 132532 ms Второй прогон primitive array: 76832 ms array list: 124047 ms Исходный код теста здесь . Как видно, массив почти вдвое быстрее списка и никакой инлайнинг, рантайм-оптимизации не помогли, хотя, казалось бы, на большом интервале вркемени эти все оптимизации должны были бы сработать и время могло бы выровняться. Но нет. UPD2 Убрал сборку мусора вообще и перегруппировал нули и получил следующее primitive array: 26177 ms array list: 54482 ms Результат очень стабилен. Думаю, на get результаты будут подобные. UPD3 Кстати, вот показательный пример для любителей вызывать руками System.gc: как видно, частая ненужная сборка мусора приводит к двухкратному снижению производительности в данном тесте.

Комментариев нет:

Отправить комментарий