Darmowy kurs Java

Interfejs List

Z podstawowych lekcji kursu dowiedzieliśmy się o prostej strukturze danych - tablicach. Niestety narzucają one na nas dużo ograniczeń, z których najważniejszym jest niezmienny rozmiar. Można to ominąć tworząc nową tablicę o większym rozmiarze i przekopiować do niej wszystkie elementy. Oczywiście rozwiązanie takie jest strasznie nieefektywne i efektywność aplikacji je wykorzystujące stałoby na niskim poziomie. Tablic powinniśmy używać tylko w przypadku, gdy znamy dokładną ilość przechowywanych elementów oraz wiemy, że nie ulegnie ona zmianie.

Kurs Programowania Java

Na szczęście do dyspozycji mamy interfejs List, dzięki któremu możemy utworzyć różne struktury zwane listami. Wśród nich najważniejsze dla nas:

    • ArrayList - implementacja tablicowa

    • LinkedList - implementacja wiązana

    Obie mają swoje wady i zalety o których jednak mowa będzie w osobnej lekcji dotyczącej list i ich implementacji. Najprościej mówiąc klasę ArrayList wykorzystujemy w przypadku, gdy najważniejszy jest czas dostępu do danych, natomiast LinkedList, gdy wiemy, że często będą wykonywane operacje usuwania, dodawania itp elementów gdzieś w środku struktury, a sprawą podrzędną są operacje wyszukiwania i szybkości dostępu do elementów listy.

    Listy deklarujemy tak jak inne obiekty, warto jednak deklarować je jako List, a przypisywać im obiekt konkretnej klasy, dzięki temu nasz kod będzie bardziej uniwersalny i w przyszłości możemy podmienić implementację bez zmiany reszty kodu.

    List lista1 = new ArrayList();
    List lista2 = new LinkedList();
    //w przypadku listy tablicowej warto dodać domyślny początkowy rozmiar - initialCapacity w konstruktorze
    List lista3 = new ArrayList(32);

    Podstawowe metody niezależne od implementacji to:

      • add(Object) - dodaje element do listy

      • remove(Object) - usuwa pierwsze wystąpienie podanego obiektu z listy

      • remove(int) - usuwa z listy element o wskazanym indeksie

      • size() - odpowiednik własności length w przypadku tablic - zwraca rozmiar listy

      • get(int) - pozwala odczytać element o wskazanym indeksie

      Przetestujmy działanie powyższych metod na liście typu ArrayList (w przypadku LinkedList byłoby identycznie).

      import java.util.ArrayList;
      import java.util.List;
      
      public class Test{
      	public static void main(String[] args){
      		//tworzymy tablicę
      		List<String> lista = new ArrayList<String>();
      		//dodajemy elementy typu Object - czyli dowolne, my dodamy ciągi znaków
      		lista.add("Asia");
      		lista.add("Basia");
      		lista.add("Krzysiek");
      		lista.add("Wojtek");
      
      		//sprawdzamy rozmiar listy
      		System.out.println("Rozmiar listy to: "+lista.size());
      
      		//usuwamy obiekt "Asia" i sprawdzamy rozmiar
      		lista.remove("Asia");
      		System.out.println("Rozmiar listy to: "+lista.size());
      
      		//usuwamy obiekt zajmujący 2 miejsce, czyli o indeksie 1 - u nas "Krzysiek"
      		lista.remove(1);
      		System.out.println("Rozmiar listy to: "+lista.size());
      
      		//na koniec przypiszmy pierwszy element listy zmiennej imie i wyświetlmy go
      		//musimy użyć rzutowania, ponieważ inaczej próbowalibyśmy przypisać Object do String
      		String imie = (String)lista.get(0);
      		System.out.println("Pierwszy element listy to: "+imie);
      
      	}
      }

      Oczywiście jest też kilka innych przydatnych metod dotyczących na przykład pierwszych i ostatnich elementów w liście - bo do nich najczęściej są odwołania.

      Ponieważ Listy są klasami generycznymi to powinniśmy im nadać konkretny typ (w komentarzu ktoś ukazał, że standardowy kompilator wręcz tego wymaga w obecnej wersji). W naszym powyższym przykładzie mogliśmy utworzyć taką listę tablicową:

      List<String> lista = new ArrayList<String>();

      a od Javy 7 możemy to nawet skrócić do:

      List<String> lista = new ArrayList<>();

      Dzięki takiemu zabiegowi pozbylibyśmy się konieczności rzutowania obiektów z typu Object na niższe typy, a co za tym idzie uprościliśmy kod. W przypadku, gdy chcielibyśmy zrobić następujące przypisanie:

      String zmienna = lista.get(1);

      wcześniej otrzymalibyśmy błąd, ponieważ próbowalibyśmy przypisać typ Object do typu String, dzięki określeniu typu generycznego wskazaliśmy, że w liście przechowujemy Stringi i problem ten znika.

      Zapisz się do newslettera

      Otrzymuj nasz Newsletter z przykładowymi pytaniami rekrutacyjnymi, wyzwaniami programistycznymi i nowościami ze świata Javy, a także informacje o nowych kursach i promocjach.

      Traktujemy Twoją prywatność poważnie. Nikomu nie udostępniamy Twojego maila no i zawsze możesz się wypisać.

      Komentarze do artykułu

      Wyłączyliśmy możliwość dodawania komentarzy. Poniżej znajdziesz archiwalne wpisy z czasów gdy strona była jeszcze hobbystycznym blogiem. Zapraszamy natomiast do zadawnia pytań i dyskusji na naszej grupe na facebooku.

      YeeeZooo

      Proponowałbym najpierw wytłumaczyć czym jest interface jednak kurs ma być dla początkujących ;)

      YeeeZooo

      Kod się nie kompiluje, trzeba jednak dodać to co piszesz o klasie generycznej i wtedy działa, chyba że coś robię źle.

      Slawek

      Kod powinien kompilować i uruchamiać się bez problemu, dodanie typu generycznego służy tylko konkretyzacji typu listy. Coś musiałeś chyba źle zrobić, bo przed chwilą to uruchomiłem :) Lekcja o interfejsach jest częściowo ukończona, mam nadzieję w weekend uda mi się ją dokończyć, podobnie lekcja o wyjątkach.

      YeeeZooo

      kopiuję cały kod ze strony jedynie nazwę klasy zmieniam na Interfejs i wyrzuca taki błąd: Note: Interfejs.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.

      Slawek

      Faktycznie zobaczyłem teraz, że od Javy 5 standardowy kompilator Javy rzuca ostrzeżenia przy próbie działania na listach, bez specyfikacji typu. Java jest językiem bezpiecznym i statycznie typizowanym, a w takim wypadku nie może sprawdzić typu. Co ciekawe w eclipse program działa ok. Więc i ja się czegoś nauczyłem :) Artykuł do lekkiej poprawki.

      YeeeZooo

      Można to dać na główną stronę :) http://www.joemonster.org/filmy/26280/Java_4_ever Swoją drogą brak mechanizmu powiadomień np: odpowiedzi na posta, za każdym razem muszę przeszukiwać wszystko czy ktoś gdzieś mi nie odpowiedział.

      Jacek

      Sławku jak do tej pory genialny kurs. Przerabiam skrupulatnie, jednak w ostatnich lekcjach zaczęło brakować mi zadań do samodzielnego wykonania : ) Korzystając z okazji chciałbym zadać pytanie. Jako, że w przyszłości planuje raczej korzystać z NB niz Eclipse, może mógłbym prosić o polecenie materiałów szkoleniowych mogących stanowić rozszerzenie tego kursu Pozdrawiam i z góry dziękuję

      Marek

      Witam wszystkich. Irytacja już mi minęła, więc piszę; mianowicie znalazłem błąd w tej lekcji. Tzn. nie tyle błąd ile niedopatrzenie, które może (tak jak w moim przypadku) prowadzić do niepotrzebnych frustracji. Dzięki konstrukcji 'List lista1 = new ArrayList(); List lista2 = new LinkedList();' Kod może i jest bardziej uniwersalny, ale nigdzie nie zostało wspomniane, że deklarując obiekt jako 'List', nawet gdy użyjemy konstruktora klasy potomnej, mamy dostęp jedynie do metod klasy 'List'. Sprawiło mi to sporo kłopotów, ponieważ przy stosowaniu metod klas potomnych (np. removeLast()) kompilator rzucał błędem. Prosiłbym o wyjaśnienie tej kwestii w kursie

      LOCODE

      dzięki! tablica działa! ale jak zrobić drugi wymiar ?

      andrew

      Witam. Jak utworzyć kilka list, ale ilość będzie pobierana z klawiatury? Próbuje coś takiego: int i=in.nextInt(System.in) List lista[i] = new ArrayList(); wiem, że nie działa, ale obrazu to co chce zrobić. Może ktoś pomoże? Pozdro

      Slawek

      Generalnie to

      List[] listy = new List[ilość];
      listy[0] = new LinkedList();
      ...
      
      Ale nie polecam czegoś takiego. Zdecydowanie lepiej będzie używać po prostu listy list, korzystając z typu generycznego.

      Piszczu

      "Najprościej mówiąc klasę ArrayList wykorzystujemy w przypadku, gdy najważniejszy jest czas dostępu do danych, natomiast LinkedList, gdy wiemy, że często będą wykonywane operacje usuwania, dodawania itp elementów gdzieś w środku struktury" - jeżeli ArrayList to odpowiednik Vector z C++ a LinkedList to List z C++ (a to wnioskuje po artykule), to to zdanie jest całkowitą głupotą. LinkedList stosujemy tylko wtedy kiedy ważna jest kolejność elementów przy dodawaniu i usuwaniu z listy. Robimy to z bardzo prostego powodu, jeżeli chcesz usunąć element ze środka ArrayList i nie zależy ci na kolejności, wtedy zamieniasz go wartościami z ostatnim elementem i kasujesz ten który będzie na końcu, co jest rozwiązaniem dużo szybszym niż dostęp do kasowanego elementu w LinkedList.

      Sławek Ludwiczak

      W Javie jest Vector i ArrayList jako oddzielne struktury - różnią się przede wszystkim tym, że Vector nie jest strukturą synchronizowaną. Przy usuwaniu elementów z środka ArrayListy w Javie wszystkie elementy leżące dalej są kopiowane na miejsce poprzedzające - co jak można się domyślić nie jest zbyt wydajne. W LinkedList zmieniana jest jedna referencja. Gdyby było tak, że w wolne miejsce zostawałaby wpisywana wartość z ostatniego elementu listy to tracilibyśmy jej podstawową funkcjonalność (po tablicach i listach zazwyczaj iterujemy - więc kolejność w większości przypadków jak najbardziej ma znaczenie). Jeśli komuś jednak bardzo zależy na rozwiązaniu takim jak sugerujesz, to nic nie stoi na przeszkodzie, żeby zaimplementować własną listę.

      Doc

      Witam serdecznie! Jestem początkujący i uczę się Javy od kilku tygodni, również z tej świetnej strony - Sławku, gratulacje i dzięki! Ośmielę się jednak nie zgodzić z Twoją wypowiedzią w poprzednim poście: "W Javie jest Vector i ArrayList jako oddzielne struktury – różnią się przede wszystkim tym, że Vector nie jest strukturą synchronizowaną." Jest dokładnie na odwrót - Vector jest synchronizowany, a ArrayList nie jest. Pozdrowienia!:)

      Sławek Ludwiczak

      Tfu, oczywiście dzięki za sprostowanie :) Jeszcze uzupełniając jaką to powoduje różnicę - przede wszystkim widoczne będzie to w wydajności (Vector będzie kilka, lub nawet kilkanaście razy wolniejszy od ArrayListy z Collections).

      Dawid

      Marek: Witam wszystkich. Irytacja już mi minęła, więc piszę; mianowicie znalazłem błąd w tej lekcji. Tzn. nie tyle błąd ile niedopatrzenie, które może (tak jak w moim przypadku) prowadzić do niepotrzebnych frustracji. Dzięki konstrukcji ‚List lista1 = new ArrayList(); List lista2 = new LinkedList();’ Kod może i jest bardziej uniwersalny, ale nigdzie nie zostało wspomniane, że deklarując obiekt jako ‚List’, nawet gdy użyjemy konstruktora klasy potomnej, mamy dostęp jedynie do metod klasy ‚List’. Sprawiło mi to sporo kłopotów, ponieważ przy stosowaniu metod klas potomnych (np. removeLast()) kompilator rzucał błędem. Prosiłbym o wyjaśnienie tej kwestii w kursie
      refresh

      Wiggy

      ArrayList lista1 = new ArrayList(); i już masz dostęp do metod klasy "nazwa_klasy"

      Wiggy

      Michał Kulas

      Jakaś masakra. Nie da się kopiować kodu źródłowego ze strony. Wkleja mi się w jednym wierszu. Po rozdzieleniu i tak kod nie działa.

      lolo

      A do czego wklejasz te kody? I mówiąc kody źródłowe ze strony masz na myśli tylko te z kursu czy też te z komentarzy? Bo mi np. do notatnika wkleja bardzo ładnie kody z kursu problemy co najwyżej stwarzają te kody z komentarzy.

      Szkolenie Java Wrocław