CodeGym /Kursy /JAVA 25 SELF /List: ArrayList i LinkedList, podstawowe operacje

List: ArrayList i LinkedList, podstawowe operacje

JAVA 25 SELF
Poziom 26 , Lekcja 1
Dostępny

1. Klasa ArrayList

W języku Java interfejs List — to kontrakt: „Jestem uporządkowaną kolekcją elementów i można pobrać element po numerze (indeksie)”.

Kluczowe właściwości listy (List):

  • Elementy są przechowywane w określonej kolejności (w przeciwieństwie do zbioru).
  • Można przechowywać duplikaty (na przykład: dwa razy "Jan").
  • Można odwołać się do elementu po indeksie: pierwszy element — indeks 0, drugi — 1 i tak dalej.
  • Można dodawać i usuwać elementy w dowolnym miejscu listy.

Najpopularniejszą implementacją interfejsu List jest ArrayList. Pod spodem używa zwykłej tablicy i automatycznie się rozszerza wraz ze wzrostem danych.

Jak utworzyć ArrayList?

import java.util.ArrayList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        // Tworzymy listę napisów
        List<String> students = new ArrayList<>();
    }
}

Wyjaśnienie

  • List<String> — to zmienna typu „lista napisów”. Zmienną deklarujemy przez interfejs, a obiekt tworzymy przez konkretną klasę (ArrayList).
  • Nawiasy kątowe <String> określają typ elementów listy (generyki, generics).

Podstawowe metody ArrayList (i w ogóle dowolnej List):

  • add(element) — dodać element na końcu listy.
  • add(index, element) — wstawić element pod konkretnym indeksem.
  • get(index) — pobrać element po indeksie.
  • set(index, element) — zastąpić element pod indeksem.
  • remove(index) — usunąć element po indeksie.
  • remove(Object) — usunąć pierwsze znalezione wystąpienie, równe przekazanemu obiektowi.
  • size() — sprawdzić liczbę elementów w liście.

Przykład: pracujemy z listą studentów

import java.util.ArrayList;
import java.util.List;

public class StudentListDemo {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();

        // Dodajemy studentów
        students.add("Jan");
        students.add("Piotr");
        students.add("Maria");

        // Wypisujemy wszystkich studentów
        System.out.println("Lista studentów: " + students);

        // Pobieramy pierwszego studenta
        String first = students.get(0);
        System.out.println("Pierwszy student: " + first);

        // Zmieniamy imię drugiego studenta
        students.set(1, "Paweł");
        System.out.println("Po zmianie: " + students);

        // Usuwamy Marię
        students.remove("Maria");
        System.out.println("Po usunięciu Marii: " + students);

        // Rozmiar listy
        System.out.println("Łącznie studentów: " + students.size());
    }
}

Rezultat:

Lista studentów: [Jan, Piotr, Maria]
Pierwszy student: Jan
Po zmianie: [Jan, Paweł, Maria]
Po usunięciu Marii: [Jan, Paweł]
Łącznie studentów: 2

Jak to się ma do naszej aplikacji?
Załóżmy, że mamy aplikację do zarządzania zadaniami studenta. Teraz możemy przechowywać listę zadań jako List<String>, a nie jako tablicę, i dynamicznie dodawać nowe zadania.

2. Klasa LinkedList: gdy liczy się szybkość wstawiania i usuwania

LinkedList — alternatywna implementacja listy. Zbudowana jako lista dwukierunkowa: każdy węzeł zna poprzedni i następny element. Jak w składzie pociągu: wstawienie „wagonu” pośrodku jest szybkie i nie wymaga przebudowy całego składu.

Tworzenie LinkedList

import java.util.LinkedList;
import java.util.List;

public class Example {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();
    }
}

Cechy LinkedList

  • Szybkie wstawianie i usuwanie na początku i w środku listy.
  • Wolny dostęp po indeksie (aby znaleźć 100. element, trzeba przejść po łańcuchu).
  • Odpowiedni, jeśli często dodajesz/usuwasz elementy nie tylko na końcu, ale także na początku lub w środku.

Przykład: użycie LinkedList

import java.util.LinkedList;
import java.util.List;

public class TaskListDemo {
    public static void main(String[] args) {
        List<String> tasks = new LinkedList<>();

        tasks.add("Obudzić się");
        tasks.add("Zjeść śniadanie");
        tasks.add("Iść na zajęcia");

        // Dodajemy zadanie na początek
        tasks.add(0, "Ustawić budzik");

        System.out.println("Lista zadań: " + tasks);

        // Usuwamy pierwsze zadanie (najwcześniejsze)
        tasks.remove(0);

        System.out.println("Po usunięciu pierwszego zadania: " + tasks);
    }
}

3. Porównanie ArrayList i LinkedList

Kryterium
ArrayList
LinkedList
Podstawa Tablica Lista dwukierunkowa
Szybki dostęp po indeksie Tak (O(1)) Nie (O(n))
Szybkie wstawianie/usuwanie na początku/w środku Nie (O(n)) Tak (O(1) — jeśli jest referencja)
Szybkie wstawianie/usuwanie na końcu Tak (zwykle O(1)) Tak (O(1))
Pamięć Zużywa mniej pamięci Więcej (dodatkowe referencje do sąsiadów)
Typowe przypadki użycia Częsty dostęp po indeksie Częste wstawianie/usuwanie

Prosta zasada:

  • Potrzebujesz szybkiego dostępu po numerze — użyj ArrayList.
  • Często dodajesz/usuwasz na początku lub w środku — użyj LinkedList.

4. Typowe operacje na listach

Iteracja po elementach listy

Zwykła pętla for

for (int i = 0; i < students.size(); i++) {
    System.out.println("Student #" + i + ": " + students.get(i));
}

Pętla for-each (najpopularniejszy sposób)

for (String name : students) {
    System.out.println("Imię: " + name);
}

Wyrażenie lambda (Java 8+)

students.forEach(name -> System.out.println("Imię: " + name));

Wyszukiwanie elementów

  • contains(element) — zwraca true, jeśli element jest na liście.
  • indexOf(element) — zwraca indeks pierwszego wystąpienia elementu lub -1, jeśli nie znaleziono.
if (students.contains("Jan")) {
    System.out.println("Jan jest na liście!");
}
int index = students.indexOf("Jan");
System.out.println("Indeks Jana: " + index);

Czyszczenie listy

clear() — usuwa wszystkie elementy.

students.clear();
System.out.println("Lista po wyczyszczeniu: " + students);

5. Kiedy używać ArrayList, a kiedy LinkedList?

Najprościej myśleć tak: ArrayList jest dobry tam, gdzie potrzebny jest szybki dostęp do elementów po indeksie, a lista zmienia się niezbyt często. Na przykład długa lista użytkowników lub historia wiadomości — głównie odczyt.

LinkedList z kolei przydaje się, gdy stale wstawiasz lub usuwasz elementy na początku/w środku. Może to być kolejka, stos albo historia cofania.

W praktyce najczęściej używa się ArrayList. A LinkedList pozostaje „narzędziem na wszelki wypadek”: leży w szufladzie, ale czasem okazuje się dokładnie tym, czego trzeba.

6. Typowe błędy przy pracy z listami

Błąd nr 1: wyjście poza zakres listy. Najczęstsza sytuacja — odwołanie do nieistniejącego indeksu. Jeśli lista ma trzy elementy, a napiszesz students.get(5), otrzymasz IndexOutOfBoundsException. Przed dostępem sprawdzaj size().

Błąd nr 2: usuwanie elementu podczas iteracji. Przy iteracji przez for-each i jednoczesnym usuwaniu elementów wystąpi ConcurrentModificationException. Do złożonych usunięć używaj pętli po indeksie lub Iterator.

Błąd nr 3: nieprawidłowe porównywanie obiektów. Jeśli przechowujesz własne obiekty (na przykład Student), metody contains i remove opierają się na equals. Jeśli go nie nadpiszesz, porównanie będzie po referencji, a nie po zawartości.

Błąd nr 4: używanie surowych typów. Nie pisz List list = new ArrayList() — zawsze podawaj typ elementów: List<String> list = new ArrayList<>(). Generyki chronią przed błędami i czynią kod czytelniejszym.

1
Zadanie
JAVA 25 SELF, poziom 26, lekcja 1
Niedostępne
Plan zajęć studenta 🗓️✍️
Plan zajęć studenta 🗓️✍️
1
Zadanie
JAVA 25 SELF, poziom 26, lekcja 1
Niedostępne
Moja prywatna lista filmów "Co obejrzeć" 🎬🍿
Moja prywatna lista filmów "Co obejrzeć" 🎬🍿
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION