Lista, która sama zmienia rozmiar
Zwykła tablica w Javie ma stałą długość: jeśli zdecydujesz się na dziesięć miejsc, masz je na zawsze. ArrayList to alternatywa o zmiennym rozmiarze z java.util: rośnie, gdy dodajesz elementy, kurczy się, gdy je usuwasz, i ma wygodne metody do rzeczy, które faktycznie robisz z listą.
Zwróć uwagę na typ w nawiasach ostrych, List<String>, który mówi kompilatorowi, że lista przechowuje wartości String. <> (tak zwany „diament”) po prawej stronie pozwala Javie wywnioskować ten sam typ bez powtarzania go. Zauważ też, że importujesz java.util.ArrayList; ta klasa nie jest dostępna domyślnie.
Deklaruj jako List, twórz jako ArrayList
Prawie zawsze zobaczysz zmienną zadeklarowaną jako interfejs List, a nie konkretny ArrayList:
List<String> names = new ArrayList<>();
To dobry nawyk, a nie reguła. Programowanie pod interfejs List sprawia, że reszta kodu nie zależy od tego, jakiej implementacji listy użyto, więc później możesz ją podmienić bez zmieniania reszty. W codziennym użyciu oba zapisy działają tak samo.
Dodawanie, odczyt i nadpisywanie
add(value)dodaje element na końcu.add(index, value)wstawia element na danej pozycji i przesuwa kolejne elementy o jedno miejsce dalej.get(index)odczytuje element na danej pozycji (indeksy od zera).set(index, value)nadpisuje istniejący element.
Indeksy liczy się od zera, a get z indeksem spoza zakresu rzuca IndexOutOfBoundsException.
Usuwanie elementów
Gdy lista przechowuje Integer, czeka klasyczna pułapka. remove(int) oznacza „usuń według indeksu”, a remove(Object) oznacza „usuń według wartości”, więc:
List<Integer> nums = new ArrayList<>(List.of(10, 20, 30));
nums.remove(1); // usuwa indeks 1 -> wartość 20
nums.remove(Integer.valueOf(20)); // usuwa wartość 20
Opakuj wartość w Integer.valueOf(...), gdy chodzi ci o „usuń tę wartość”, a nie „usuń ten indeks”.
Rozmiar, zawieranie i wyszukiwanie indeksu
List.of(...) szybko tworzy niemodyfikowalną listę; przekazanie jej do konstruktora ArrayList daje modyfikowalną kopię z tymi wartościami na start.
Pętla po ArrayList
Najczytelniejsza pętla to rozszerzone for (pętla for-each):
Gdy potrzebujesz też indeksu, użyj pętli z licznikiem oraz size() i get(i):
Jedna zasada: nie dodawaj ani nie usuwaj elementów listy, gdy pętla for-each po niej iteruje, bo to rzuca ConcurrentModificationException. Aby bezpiecznie usunąć pasujące elementy, użyj removeIf:
Sortowanie
Collections.sort porządkuje listę w miejscu według porządku naturalnego (alfabetycznie dla napisów, liczbowo dla liczb):
Dla własnego porządku przekaż Comparator do list.sort(...), na przykład names.sort(Comparator.comparingInt(String::length)), aby sortować według długości.
ArrayList przechowuje obiekty, nie typy proste
Nie możesz napisać ArrayList<int>. Typy generyczne działają tylko z typami obiektowymi, więc używaj klas opakowujących Integer, Double, Boolean i tak dalej:
Autoboxing w Javie sam konwertuje między int a Integer, więc kod czyta się naturalnie. Pamiętaj tylko, że sama lista przechowuje obiekty Integer.
Dalej: HashMap
ArrayList to właściwe narzędzie, gdy liczy się kolejność i pozycja. Gdy musisz wyszukiwać elementy według klucza, na przykład użytkownika po nazwie albo cenę po kodzie produktu, potrzebujesz HashMap, którą omawia następna strona.
Najczęściej zadawane pytania
Jak utworzyć ArrayList w Javie?
Zadeklaruj ją z typem elementów w nawiasach ostrych i wywołaj konstruktor: ArrayList<String> names = new ArrayList<>();. <> po prawej stronie przypisania (operator diamentu) pozwala Javie wywnioskować typ. Zwykle zmienną deklaruje się jako interfejs List: List<String> names = new ArrayList<>();.
Czym różni się tablica od ArrayList w Javie?
Zwykła tablica ma stałą długość ustaloną przy tworzeniu i może przechowywać typy proste, takie jak int. ArrayList rośnie i kurczy się automatycznie, gdy dodajesz i usuwasz elementy, przechowuje tylko obiekty (więc int staje się Integer) i ma metody takie jak add, remove, contains i size. Używaj tablicy dla danych prostych o stałym rozmiarze, a ArrayList, gdy rozmiar się zmienia.
Jak usunąć element z ArrayList?
Wywołaj remove(index), aby usunąć element według pozycji, albo remove(object), aby usunąć pierwszy pasujący element. Uważaj na listy Integer: list.remove(2) usuwa indeks 2, a list.remove(Integer.valueOf(2)) usuwa wartość 2. Aby usuwać w trakcie pętli, użyj remove() z Iterator albo removeIf(...), co pozwala uniknąć ConcurrentModificationException.