Dziś kontynuujemy temat kolekcji. W poprzednim wpisie zostały omówione Sety, dziś natomiast zajmiemy się Listami. Temat będzie nieco krótszy od Setów (uffff!), chociażby ze względu na to że omówimy tylko najbardziej popularne implementacje, ArrayList oraz LinkedList. Zapraszam! 🙂
01. Lista a Set - podobieństwa i różnice
Niezależnie od implementacji, Sety oraz Listy zaliczamy do grona kolekcji, wywodzą się od wspólnego interfejsu Collection. Listy tak samo jak Sety, są generyczne. Czym są generyki zarysowałem w poprzednim wpisie odnośnie Setów.
Główną różnicą jest to iż Lista pozwala przechowywać duplikaty, dokładnie ten sam obiekt, lub taki sam obiekt, możemy dodać wielokrotnie do Listy, gdzie Set nam to uniemożliwi.
Wiele stron oraz kursów w różnicach podaje że Lista jest uporządkowana, natomiast Set nie. Nie jest to prawda! Wszystko zależy od użytej implementacji Setu np. LinkedHashSet zachowuje kolejność dodania 😊
02. Listy
Niezależnie od implementacji z jakiej korzystamy, dysponujemy takim samym podstawowym arsenałem funkcjonalności. Możemy dodawać pojedyncze elementy do listy, dodawać całe kolekcje, usuwać elementy, sortować, iterować po wszystkich elementach, lub pobrać konkretny element z listy.
Nie będę omawiać tutaj każdego elementu z osobna, operacje są tak domyślne że zachęcam was do samodzielnego eksperymentowania! 😊
Główna różnica leży w wydajności konkretnych implementacji dla danej operacji, np. dodawanie wielu elementów do ArrayListy jest niewydajne, do tego zdecydowanie lepiej nadaje się LinkedLista.
List<Hero> heroList = new LinkedList<>(); heroList.add(new Person("Arek")); heroList.add(new Person("Arek")); heroList.add(new Person("Dominika")); heroList.add(new Person("Karolina")); heroList.add(new SuperPerson("Dominika")); for (Hero hero : heroList) { System.out.println(hero); }
//skorzystałem z tych samych klas co w omówieniu Setów
03. ArrayList
ArrayList jest tak naprawdę dynamiczną tablicą. W ramach przypomnienia odsyłam do lekcji o tablicach, zauważ że podczas tworzenia tablicy deklarujemy jej wielkość która jest niezmienna.
ArrayList wewnętrznie używa tablicy do przechowywania danych, a w momencie dodawania sprawdza czy zbliżamy się do końca tablicy, jeśli tak, tworzona jest nowa tablica o większym rozmiarze, i przepisywane są do niej elementy ze starej tablicy.
Jeśli będziemy dodawać bardzo dużo elementów do ArrayListy, możemy mieć problemy związane z wydajnością. ArrayList ma natomiast przewagę jeśli chcemy odczytywać elementy z wybranych indexów. Dostęp do każdego elementu jest stały.
04. LinkedList
LinkedList wewnętrznie przechowuje elementy w podwójnie związanej liście elementów. Każdy z elementów posiada wskaźnik do następnego jak i poprzedniego elementu. Iterowania po wszystkich elementach jest szybkie, natomiast pobranie konkretnego elementu z danego indexu wymaga większego nakładu pracy. Wewnętrznie i tak musimy przejść przez wszystkie poprzedzające elementy aż dojdziemy do konkretnego indexu.
Zaletą LinkedListy w porównaniu z ArrayListą jest szybkość wykonywania operacji dodawania oraz usuwania.
Podsumowanie
LinkedLista powinna być wybierana w przypadku gdy nie posiadamy „losowych” pobrań elementów (z konkretnego indexu), oraz gdy na danej liście stosujemy wiele operacji dodawania lub usuwania elementów.
Jeśli zaś liczba elementów w liście jest stała, oraz potrzebujemy bardzo szybkiego dostępu do elementów znajdujących się na konkretnych pozycjach, wtedy zdecydowanie lepszym wyborem będzie ArrayList.