Kolekcje Javy – Interfejs List – ArrayList
W tym artykule przyjrzymy się gotowym kolekcjom opartych na interfejsie List
. Obie omawiane klasy implementują go oraz interfejs Iterable
w związku z tym ich obsługa z puntu widzenia programisty będzie bardzo podobna. Różnice polegają głównie na sposobie reprezentacji danych w pamięci i algorytmów obsługi takich jak dodawanie elementów, odczyt czy też usuwanie. Wpis jest częścią artykułów o kolekcjach w Javie.
Klasa ArrayList
ArrayList
jest implementacją listy, w taki sposób, że kolejne elementy znajdują się obok siebie w wewnętrznej tablicy. Element i oraz i+1 sąsiadują ze sobą nie tylko jako elementy kolekcji, ale również w pamięci operacyjnej komputera. Główną różnicą w stosunku do poznanych wcześniej tablic jest to, że rozmiar może zmieniać się dynamicznie w trakcie działania programu.
W Javie co prawda tablice pozwalają na ustalenie rozmiaru tablicy po uruchomieniu aplikacji, jednak jeśli już utworzymy taką tablicę, to nie można zmieniać jej rozmiarów. W przypadku ArrayList
to ograniczenie nie istnieje i można dowolnie rozszerzać lub zmniejszać rozmiar kolekcji.
ArrayList
posiada w swojej implementacji pojemność (ang. capacity). Jej rozmiar jest co najmniej tak duży jak rozmiar przechowywanej kolekcji. Nie jest sprecyzowane w jaki sposób i kiedy rozszerza się pojemność kolekcji. Wiadomo tylko, że dodawanie elementów posiada zamortyzowany koszt.
Kolekcje ArrayList
nie są automatycznie synchronizowane w związku z czym w przypadku dostępu do kolekcji przez wiele wątków należy zadbać o mechanizm synchronizacji samemu. Jednakże problemem wielowątkowości aplikacji zajmiemy się w przyszłości.
ArrayList – jak używać
Klasa ArrayList
jest klasą generyczną co oznacza, że można przechowywać w kolekcji dowolny typ obiektowy. W praktyce istnieje jeszcze stara wersja, która przechowuje obiekty klasy Object
, ale w obecnej wersji Javy nie ma sensu korzystać z niej gdyż korzystanie z niej wymaga niewygodnego rzutowania, którego zalecamy unikać gdy nie jest konieczne.
Konstruktory oraz tworzenie obiektu listy
ArrayList<E>()
– tworzy pustą listę o pojemności 10.ArrayList<E>(int capacity)
– Tworzy pustą listę o pojemności podanej w parametrze.
Aby utworzyć pustą listę tablicową można użyć następującego kodu.
1 |
ArrayList<String> listaZakupow = new ArrayList<>(); |
Można też skorzystać ze zmiennej interfejsu List
.
1 |
List<String> listaZakupow = new ArrayList<>(); |
Metody dostarczone przez klasę ArrayList
boolean add(E element)
– Dodaje na końcu listy element.void add(int index, E element)
– dodaje element na pozycji index (licząc od 0). Element znajdujący się dotychczas na tej pozycji oraz wszystkie o indeksie większym zostają przesunięte w prawo.E remove(int index)
– usuwa z listy element o wskazanym indeksie. Pozostałe elementy za nim przesuwa w lewo.void clear()
– usuwa wszystkie elementy z listy.E set(int index, E element)
– zamienia element we wskazanym indeksie na ten podany w argumencie.<T> T[] toArray(T[] array)
– zwraca listę w postaci tablicowej.void trimToSize()
– zmniejsza pojemność wewnętrznej tablicy listy do rozmiaru kolekcji.E get(int index)
– zwraca element o podanym indeksie.ListIterator<E> listIterator(int index)
– zwraca iterator umieszczony na obiekcie o podanym indeksie.void sort(Comparator<? super E> collection)
– sortuje listę wg. podanego komparatora. Aby było to możliwe musimy zaimplementować interfejs Comparable oraz metodę compareTo w obiektach klas, które są elementami kolekcji.int size()
– zwraca rozmiar listy (liczbę aktualnie przechowywanych obiektów, a nie pojemności listy).
Poniżej pokażemy jak w praktyce używać podanych wyżej metod.
1 2 3 4 5 6 7 8 9 10 11 12 |
List<String> listaZakupow = new ArrayList<>(); //Utworzenie kolekcji listaZakupow.add("Jabłko"); listaZakupow.add("Banan"); listaZakupow.add("Grejpfrut"); //dodanie trzech elementów do listy for(String z: listaZakupow){ system.out.Println(z); //dostęp do elementów przy pomocy pętli for } String tmp = listaZakupow.get(1); //zwróci drugi element listy (numeracja tak jak w zwykłej tablicy zaczyna się od 0). listaZakupow.remove(1)//usuwa drugi element z listy int liczbaZakupow = listaZakupow.size(); //zwróci liczbę elementów na liście zakupów |
ArrayList podsumowanie
Na potrzeby akademickie ta klasa jest w zupełności wystarczająca gdyż zapewnia wszystkie dostępne operacje potrzebne do obsługi list
i jest dobrze zoptymalizowana. Największe zastrzeżenie może budzić sytuacja, gdy należy modyfikować dużo elementów w środku kolekcji. Wtedy ArrayList
wykonuje różne czynności, które nie są zbyt efektywne. Może się okazać, że korzystniejsze będzie użycie drugiej implementacji czyli list
powiązanych LinkedList
dlatego polecamy używania zmiennej interfejsu List gdyby zaszła potrzeba zmiany jednej implementacji na drugą.