Właściwie napisałem post na blogu na ten temat 2 miesiące temu. Artykuł jest przeznaczony dla C #, List<T>ale Java ArrayListma bardzo podobną implementację. Ponieważ ArrayListjest implementowany przy użyciu tablicy dynamicznej, zwiększa się na żądanie. Dlatego konstruktor pojemności ma na celu optymalizację.
Gdy wystąpi jedna z tych operacji zmiany rozmiaru, ArrayList kopiuje zawartość tablicy do nowej tablicy, która ma dwukrotnie większą pojemność niż stara. Ta operacja działa w czasie O (n) .
Przykład
Oto przykład, jak ArrayListzwiększyłby się rozmiar:
10
16
25
38
58
... 17 resizes ...
198578
297868
446803
670205
1005308
Tak więc lista zaczyna się od pojemności 10, po dodaniu 11. pozycji jest ona zwiększana o 50% + 1do 16. Na 17. pozycji wartość ArrayListjest ponownie zwiększana do 25i tak dalej. Rozważmy teraz przykład, w którym tworzymy listę, na której żądana pojemność jest już znana jako 1000000. Utworzenie konstruktora ArrayListbez rozmiaru wywołuje ArrayList.add 1000000czasy, które normalnie przyjmują O (1) lub O (n) przy zmianie rozmiaru.
1000000 + 16 + 25 + ... + 670205 + 1005308 = 4015851 operacji
Porównaj to przy użyciu konstruktora, a następnie wywołanie, ArrayList.addktóre ma gwarantowane działanie w O (1) .
1000000 + 1000000 = 2000000 operacji
Java vs C #
Java działa jak powyżej, zaczynając od 10i zwiększając każdą zmianę rozmiaru o 50% + 1. C # zaczyna się od 4i rośnie znacznie agresywniej, podwajając się przy każdej zmianie rozmiaru. 1000000Dodaje przykład od góry do C # używa 3097084operacji.
Bibliografia