Chociaż w większości scenariuszy odpowiedzi proponujące użycie ArrayList są sensowne, tak naprawdę nie znaleziono odpowiedzi na pytanie dotyczące względnej wydajności.
Jest kilka rzeczy, które możesz zrobić z tablicą:
- Stwórz To
- ustaw przedmiot
- dostać przedmiot
- sklonuj / skopiuj to
Ogólny wniosek
Chociaż operacje pobierania i ustawiania są nieco wolniejsze na ArrayList (odpowiednio 1 i 3 nanosekundy na każde wywołanie na mojej maszynie), jest bardzo mały narzut związany z używaniem ArrayList w porównaniu z tablicą do jakiegokolwiek nie intensywnego użycia.Należy jednak pamiętać o kilku kwestiach:
- zmiana rozmiaru operacji na liście (podczas połączenia
list.add(...)
) są kosztowne i należy spróbować ustawić początkową pojemność na odpowiednim poziomie, jeśli to możliwe (zauważ, że ten sam problem pojawia się podczas korzystania z tablicy)
- w przypadku prymitywów tablice mogą być znacznie szybsze, ponieważ pozwolą uniknąć wielu konwersji boksu / rozpakowania
- aplikacja, która pobiera / ustawia wartości tylko w ArrayList (niezbyt często!), może uzyskać wzrost wydajności o ponad 25% po przełączeniu na tablicę
Szczegółowe wyniki
Oto wyniki, które zmierzyłem dla tych trzech operacji przy użyciu biblioteki testów porównawczych jmh (czasy w nanosekundach) z JDK 7 na standardowej maszynie stacjonarnej x86. Należy pamiętać, że ArrayList nigdy nie jest zmieniany w testach, aby upewnić się, że wyniki są porównywalne. Kod testu dostępny tutaj .
Array / ArrayList Creation
Przeprowadziłem 4 testy, wykonując następujące instrukcje:
- createArray1:
Integer[] array = new Integer[1];
- createList1:
List<Integer> list = new ArrayList<> (1);
- createArray10000:
Integer[] array = new Integer[10000];
- createList10000:
List<Integer> list = new ArrayList<> (10000);
Wyniki (w nanosekundach na połączenie, 95% ufności):
a.p.g.a.ArrayVsList.CreateArray1 [10.933, 11.097]
a.p.g.a.ArrayVsList.CreateList1 [10.799, 11.046]
a.p.g.a.ArrayVsList.CreateArray10000 [394.899, 404.034]
a.p.g.a.ArrayVsList.CreateList10000 [396.706, 401.266]
Wniosek: brak zauważalnej różnicy .
uzyskać operacje
Przeprowadziłem 2 testy, wykonując następujące instrukcje:
- getList:
return list.get(0);
- getArray:
return array[0];
Wyniki (w nanosekundach na połączenie, 95% ufności):
a.p.g.a.ArrayVsList.getArray [2.958, 2.984]
a.p.g.a.ArrayVsList.getList [3.841, 3.874]
Wniosek: uzyskanie z tablicy jest około 25% szybsze niż pobieranie z ArrayList, chociaż różnica jest rzędu jednego nanosekundy.
ustawić operacje
Przeprowadziłem 2 testy, wykonując następujące instrukcje:
- Setlista:
list.set(0, value);
- setArray:
array[0] = value;
Wyniki (w nanosekundach na połączenie):
a.p.g.a.ArrayVsList.setArray [4.201, 4.236]
a.p.g.a.ArrayVsList.setList [6.783, 6.877]
Wniosek: ustawione operacje na tablicach są o około 40% szybsze niż na listach, ale jeśli chodzi o get, każda operacja zestawu zajmuje kilka nanosekund - więc aby różnica osiągnęła 1 sekundę, trzeba ustawić pozycje na setkach listy / tablicy milionów razy!
klon / kopia
ArrayList jest konstruktor kopiujący delegatów Arrays.copyOf
więc wydajność jest identyczna kopia tablicy (kopiowanie tablicę via clone
, Arrays.copyOf
lub System.arrayCopy
nie ma istotnego znaczenia z punktu widzenia wydajności ).