Powstaje standardowe pytanie: jak zainicjować listę? Poniższy kod nie będzie działać: Spowoduje to błąd kompilacji: Nazwy zmiennych lokalnych mogły nie zostać zainicjowane . Specyfikacja Java wymaga, aby wszystkie zmienne lokalne (te, które istnieją na stosie) były inicjalizowane odpowiednimi wartościami. Można to zrobić w następujący sposób: Bez wątpienia lista musi zostać zainicjowana. Możesz albo utworzyć listę w pierwszym wierszu, albo zrobić coś mądrzejszego i zastosować leniwą inicjalizację , tak jak zrobiliśmy to w metodzie getAllNames() . W takim przypadku lista zostanie utworzona tylko wtedy, gdy będzie to konieczne - jeśli warunki początkowe nie zostaną spełnione, lista nigdy nie pojawi się na stercie. Tu dochodzimy do głównego pytania: jaki rozmiar ustawić dla listy? Najlepszą opcją jest podanie mu dokładnego rozmiaru. Przykład: W tym przypadku musi zostać zwróconych dokładnie n nazw, w wyniku czego zostanie utworzona kolekcja n elementów. Jednak dokładna wartość n nie zawsze jest znana. Nawet w podanym przykładzie, co by było, gdyby n=1000 i dostępnych było tylko 100 nazw? Podczas pracy z kolekcjami najpopularniejszą metodą jest wywołanie konstruktora domyślnego. Jeśli spojrzeć na kod źródłowy Java (wersja 1.6) Jak widać, domyślnie tworzona jest lista 10 elementów . Oznacza to, że możemy bezpiecznie użyć konstruktora domyślnego, gdy nie planujemy przechowywać na liście więcej niż 10 elementów. Co się stanie, jeśli spróbujesz dodać jedenasty element? No cóż, nic złego... element zostanie pomyślnie dodany. Przyjrzyj się metodzie: Rozmiar tablicy jest kontrolowany przez metodę zapewnieniaCapacity . Rozmiar zwiększa się 1,5 razy . Tworzona jest nowa tablica i elementy są do niej przenoszone. Jeśli ustawimy rozmiar na 10, to na 11 elemencie:
public List
getAllNames() { List
names; if (/*необходимые условия выполнены*/) { names = new ArrayList
(); /*заполнение списка*/ } return names; }
List
names = null; List
names = new ArrayList
(); List
names = new ArrayList
(0); List
names = new ArrayList
(size);
public List
getTopNames (int n) { List
names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList
(n); /*заполнение списка*/ } return names; }
names = new ArrayList
();
/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; }
public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
- rozmiar zmienia się na 10 * 3 / 2 + 1 = 16
- następny wzrost = 16 * 3 / 2 + 1 = 25
- następny wzrost = 25 * 3 / 2 + 1 = 39 i tak dalej.
- Twórz kolekcję tylko wtedy, gdy jej potrzebujesz , w przeciwnym razie zainicjuj ją na wartość null lub użyj Collections.EMPTY_LIST .
- Jeśli znasz dokładny wymagany rozmiar , określ go w konstruktorze kolekcji.
- Jeśli masz pewność, że liczba elementów nie przekroczy 10 , możesz skorzystać z konstruktora domyślnego.
- Ryzyko związane z tworzeniem kolekcji o zerowym rozmiarze polega na tym, że częstotliwość tworzenia nowych tablic i kopiowania danych może być większa. Musisz bardzo dokładnie przemyśleć, czy korzystanie z kolekcji w rozmiarze zero przyniesie korzyści .
- Jeśli na początku metody zainicjowałeś zbyt dużą kolekcję i chcesz ją zmniejszyć, istnieje metoda trimToSize() .
GO TO FULL VERSION