„klasy kolekcji”
DESCRIPTION
„Klasy kolekcji”. Techniki i języki programowania. by Szymon Natanek. Kolekcje obiektów. Tablice: Klasa Arrays Listy: Klasy: ArrayList, LinkedList, Vector, Stack Zbiory: Klasy: TreeSet, HashSet, LinkedHashSet Mapy: - PowerPoint PPT PresentationTRANSCRIPT
„„Klasy kolekcji”Klasy kolekcji”
by Szymon Natanek
Techniki i języki programowania
Kolekcje obiektówKolekcje obiektów Tablice:
Klasa Arrays
Listy:
Klasy: ArrayList, LinkedList, Vector, Stack
Zbiory:
Klasy: TreeSet, HashSet, LinkedHashSet
Mapy:
Klasy: HashMap, LinkedHashMap, WeakHashMap, TreeMap, IdentityHashMap, HashTable
TabliceTablice Tablica w Javie jest ciągiem obiektów (a raczej referencji do obiektów). Jest prostą
sekwencją liniową, pozwalającą na szybki dostęp do elementów.
Tablice posiadają ograniczenie rozmiaru. Można stworzyć tablicę o określonym rozmiarze, ale nie można tego rozmiaru zmienić w czasie życia obiektu.
Aby uniknąć powyższego problemu, po zapełnieniu tablicy, można utworzyć nową, o większym rozmiarze i skopiować zawartość poprzedniej do niej. Jest to jednakże rozwiązanie mało wygodne.
Inicjowanie tablic:
MyObj[] tablica1; // niezainicjowana
MyObj tablica2[]; // jak wyżej
MyObj[] tablica3 = new MyObj[5] // zainicjowana tablica 5 elementowa
MyObj[] tablica4 ={new MyObj(), new MyObj()} /* zainicjowana tablica 2 elementowa */
Zaletą tablicy jest sprawdzanie zakresu, dlatego też nie możliwe jest wyjście poza ściśle określony zakres tablicy, jak miało to miejsce w C lub C++
Tablice - ciąg dalszyTablice - ciąg dalszy
Tablicy niezainicjowanej nie można użyć. Jeżeli nastąpi odwołanie do niezainicjowanej tablicy, kompilator powiadomi nas o błędzie:
int[] tablica1; // Tablica nie zainicjowana
int[] tablilca2 = new int[6];
int length = tablica1.length + tablica2.length; // Błąd
Tablica posiada składową tylko do odczytu length, będącą długością tablicy (lecz nie obecnej ilości obiektów, tylko ilość obiektów jakie można umieścić).
W przeciwieństwie do klas kontenerowych, które przechowują referencje do obiektów, tablice mogą przechowywać również zmienne typu podstawowego.
Tablice mogą być zwracane przez funkcje. W C lub C++ można było zwrócić wskaźnik do tablicy jako wynik funkcji. Java natomiast daje możliwość zwracania całej tablicy. Zwolnieniem pamięci z takiej tablicy nie trzeba się martwić, ponieważ po zniknięciu wszystkich odwołań do niej, zostanie automatycznie usunięta.
ArraysArrays Klasa Arrays, zamieszczona w pakiecie java.util, posiada zestaw metod statycznych
do wykonywania operacji na tablicach:
equals(tablica1, tablica2); // Porównuje tablice pod względem równości
fill(tablica, wartość); // Wypełnia tablicę określoną wartością
sort(tablica, comparator); // Sortuje tablicę (comparator opcjonalny)
binarySearch(tablica, szukany_element, comparator ); /*Wyszukuje element w tablicy posortowanej*/
Powyższe metody są przeciążone dla każdego z podstawowych typów i klasy Object
Ponadto klasa Arrays posiada metodę toList(), która zmienia tablicę w kontener List
Do kopiowania tablicy służy statyczna metoda System.arraycopy(), pozwalająca na kopiowanie tablic, szybciej niż za pomocą własnej pętli for. Jest ona przeciążona tak, że obsługuje tablice wszystkich typów.
Do porównywania elementów tablicy służy metoda compareTo() zamieszczona w interfejsie java.lang.Comparable
Porównywanie elementówPorównywanie elementów Do porównywania elementów tablicy służy metoda compareTo() zamieszczona w
interfejsie java.lang.Comparable. Metoda ta jest niezbędna do działania metody sort()
Przykład 1 – porównanie z wykorzystaniem compareTo():
import java.util.*;
public class CompType implements Comparable {
int value;
...
public int compareTo(Object obj) {
int val = ((CompType)obj).value;
return (value < val ? –1 : (value == val ? 0 : 1));
}
Porównywanie elementów – ciąg dalszyPorównywanie elementów – ciąg dalszy
Przykład 2 – porównanie przy użyciu compare():
import java.util.*;
public class MyComp implements Comparable {
public int compare(Object o1, Object o2) {
int val = ((CompType)o1).value;
int val2 = ((CompType)o2).value;
return (val1 < val2 ? –1 : (val1 == val2 ? 0 : 1));
}
Wyszukiwanie elementówWyszukiwanie elementów Metody porównań wykorzystywane są również do wyszukiwania elementów za
pomocą binarySearch().
Przeszukiwanie tablic, jak sama nazwa sugeruje, odbywa się stosując wyszukiwanie binarne. Należy pamiętać o tym, aby nie wyszukiwać elementów w tablicy nieuporządkowanej, gdyż wynik jest nieprzewidywalny (nieskończona pętla rekurencyjna, lub błędny wynik).
Jeżeli do sortowania tablicy stosujemy Comparator, to trzeba włączyć ten Comparator podczas szukania:
import java.util.*;
public class search {
...
MyComparator comp = new MyComparator();
Arrays.binarySearch(tablica, szukany_element, comp);
}
Kontenery (Containers)Kontenery (Containers) Kontenery dzielą się na dwie grupy
Kolekcje:
W skład kontenerów wchodzą trzy komponenty i po kilka ich implementacji tj. ArrayList, LinkedList, Vector, Stack, TreeSet, HashSet, LinkedHashSet, HashMap, LinkedHashMap, WeakHashMap, TreeMap, IdentityHashMap, HashTable
Lista (List) – przechowuje elementy w określonej kolejności, może przechowywać powtarzające się elementy
Zbiór (Set) – przechowuje elementy w dowolnej kolejności, nie może zawierać elementów zduplikowanych
Odwzorowanie:
Odwzorowanie (Map) – grupa par obiektów typu klucz-wartość
Kontenery diagram IKontenery diagram IDiagram kontenerów:Diagram kontenerów:
Kontenery diagram IIKontenery diagram II
Diagram kontenerów II:Diagram kontenerów II:
Jak widać na diagramie, tak naprawdę są tam tylko trzy komponenty: Jak widać na diagramie, tak naprawdę są tam tylko trzy komponenty: MapMap, , ListList i i SetSet. Reszta to interfejsy, klasy abstrakcyjne i klasy pochodne.. Reszta to interfejsy, klasy abstrakcyjne i klasy pochodne.
Kontenery diagram IIIKontenery diagram III
Diagram kontenerów III:Diagram kontenerów III:
Jeszcze jeden diagram, tym razem w większym uproszczeniuJeszcze jeden diagram, tym razem w większym uproszczeniu
Kontenery - wypełnianieKontenery - wypełnianie
Wypełnianie kontenerów:
Dla kontenerów istnieje klasa towarzysząca Collections zawierająca statyczne metody usługowe, między nimi metodę fill(). Metoda ta zastępuje elementy, które już są na liście. Działa tylko dla klasy List, a nie działa dla Map i Set.
fill() ma tę samą wadę, co dla tablic – wypełnia całą listę referencją do jednego obiektu. Przez to fill() jest niezbyt użyteczne.
Ponadto elementy można dodawać do kontenerów za pomocą metod add() i put(). Będą one omówione dalej, przy okazji omówienia interfejsu Collection.
Kontenery – wypisywanie IKontenery – wypisywanie I
Wypisywanie zawartości kontenerów:
Zawartość kontenerów można wypisać funkcją println() pobierającą jako parametr referencję do kontenera. Przy odwołaniu, gdzie oczekiwany jest typ String domyślnie wywoływana jest metoda toString(). Metodę toString można przeciążać dla wszystkich typów obiektów.
Przykład:
import java.util.*;
public class ListPrint {
List list = new ArrayList();
for(int i=0; i<10; i++)
list.add(”element listy”);
System.out.println(list); // Wywoła domyślnie toString()
}
Kontenery – wypisywanie IIKontenery – wypisywanie II
Wypisywanie adresu elementów kontenerów:
Jeżeli do wypisania adresu obiektu w pamięci użyty zostanie this, spowoduje to powstanie rekursji i wygenerowana zostanie niekończąca się lista wyjątków. Aby tego uniknąć należy zastosować super zamiast this.
Przykład 1: Przykład 2:
import java.util.*;
public class APrint1 {
public class MyObject {
public String toString() {
return ”adress:” + this;
}}
public static void main(String[] args) {
List list = new ArrayList();
for(int c; c<10; c++)
v.add(new MyObject);
System.out.println(list); }
import java.util.*;
public class APrint1 {
public class MyObject {
public String toString() {
return ”adress” + super;
}}
public static void main(String[] args) {
List list = new ArrayList();
for(int c; c<10; c++)
v.add(new MyObject);
System.out.println(list);}
zamiast
Kontenery – wypisywanie IIIKontenery – wypisywanie III Sposób wyświetlania:
Zawartość kontenerów, wypisana za pomocą polecenia println, jest wyświetlana w różny sposób, za zależności, jaki kontener jest wypisywany
List:
Zawartość kontenera jest wyświetlana w nawiasach kwadratowych:
”[element1, element2, element1, element3]”
• Set:
• Zawartość kontenera jest wyświetlana jak przy List, z tą różnicą, że elementy się nie powtórzą (wynika to z właściwości zbioru Set):
”[element1, element2, element3]”
• Map:
• Zawartość kontenera jest wyświetlana w nawiasach klamrowych, w parach klucz = wartość_skojarzona :
”{klucz1=element1, klucz2=element2, klucz3=element3}”
Wady kontenerówWady kontenerów
Nieznany typ:
Konsekwencje:
Brak ograniczeń co do typu zamieszczanych obiektów.
Trzeba wykonywać rzutowanie do właściwego typu przed użyciem obiektu
Wadą kontenerów jest brak informacji o przechowywanym typie. Kontener przechowuje odwołania do obiektów klasy Object, będącej klasą bazową wszystkich innych.
Klasa ArrayList o określonym typie:public class MyList {
private List list = new ArrayList(); // przesłanianie funkcji, a nie przeciążanie
public void add(MyObj o) { list.add(o); } // jak w przypadku dziedziczenia
public MyObj get(int index) { return (MyObj)list.get(index); }
public int size() { return list.size(); }
}
Wymusza typ
IteratoryIteratory
Iterator jest obiektem służącym do przemieszczania się po ciągu elementów i wybieranie napotkanych obiektów.
Iterator może być pobrany dzięki metodzie iterator(), zwracającej iterator do danego kontenera.
Funkcje iteratora:
next() – uzyskuje następny obiekt z ciągu, a zwraca poprzedni obiekt
hasNext() – sprawdza, czy są następne obiekty
remove() – usuwa ostatni zwrócony przez iterator obiekt
Interfejs Collection – funkcjeInterfejs Collection – funkcje
Funkcje interfejsu Collection:
boolean add(Object) – dodaje argument (zwraca false, jeśli go nie doda)
boolean addAll(Collection) – umieszcza wszystkie elementy kontenera argumenu (zwraca true, Jeżeli został dodany jakiś obiekt)
void clear() – usuwa wszystkie elementy
boolean contains(Objest) – sprawdza, czy obiekt jest w kontenerze
boolean containsAll(Collection) – sprawdza, czy kontener zawiera wszystkie obiekty argumentu
boolean isEmpty() – sprawdza, czy kontener jest pusty
Iterator iterator() – zwraca iterator
boolean remove(Object) – usuwa obiekt
boolean removeAll(Collection) – usuwa wszystkie obiekty zawarte w argumencie
Interfejs Collection – funkcji ciąg dalszyInterfejs Collection – funkcji ciąg dalszy
Funkcje interfejsu Collection ciąg dalszy:
boolean retainAll(Object) – pozostawia przecięcie, z teorii zbiorów, dwóch kontenerów
int size() – Zwraca liczbę elementów zawartych w kontenerze
Object[] toArray() – zamienia kontener na tablicę
Object[] toArray(Object[] a) – jak wyżej, typ tablicy przyjmuje typ argumentu
Interfejs Collection nie posiada funkcji get() pozwalającej na swobodny dostęp do elementów. Do kategorii Collection należą też zbiory Set, toteż swobodny dostęp do nich byłby bezsensowny.
W celu wydobycia elementu należy użyć iteratora.
Interfejs ListInterfejs List
Funkcje interfejsu List:
add(Object) – wstawia element (addFirst(), addLast() dla LinkedList)
get() – pobiera element (getFirst(), getLast() dla LinkedList)
remove() – usuwa element (removeFirst(), removeLast() dla LinkedList)
iterator() – zwraca iterator
MyClass[] toArray(MyClass[] a) – jak wyżej, typ tablicy przyjmuje typ argumentu
ArrayList:
Implementacja interfejsu List jako tablicy. Umożliwia szybszy dostęp do jej elementów, kosztem wolniejszego ich wstawiania i usuwania.
LinkedList:
Zapewnia optymalny dostęp sekwencyjny, usuwanie i wstawianie elementów do środka listy. Powolna w przypadku swobodnego dostępu. LinkedList pozwala na zaimplementowanie stosu oraz kolejki.
StosStos
Główne metody stosu:
public class MyStack {
private LinkedList list = new LinkedList;
public void push(Object o) { list.addFirst(o); }
public Object top() { return list.getFirst(); }
public Object pop() { return list.removeFirst|(); }
...
}
Stos jest przedstawiany jako kontener typu last-in, first-out (LIFO). Można go stworzyć na podstawie LinkedList:
KolejkaKolejka
Główne metody kolejki:
public class MyQueue {
private LinkedList list = new LinkedList;
public void put(Object o) { list.addFirst(o); }
public Object get() { return list.removeLast(); }
...
}
Kolejkę jest kontenerem typu first-in, first-out (FIFO). Można ją stworzyć na podstawie LinkedList:
Interfejs SetInterfejs Set
Set ma ten sam interfejs co Collection, pomimo to zachowuje się inaczej. Set nie pozwala na przechowywanie więcej niż jednego egzemplarza wartości każdego z obiektów. Interfejs ten nie zapewnia utrzymania elementów w żadnym porządku. Elementy Object zamieszczane w Set muszą definiować metodę equals(), w celu ustalenia, czy element już przypadkiem nie należy do zbioru.
HashSet:
Zapewnia krótki czas lokalizacji elementu. Wymaga zdefiniowania metody hashCode() i equals() dla elementów klasy Object.
TreeSet:
Zbiór uporządkowany na podstawie drzewa. Dzięki niemu można pobierać uporządkowany ciąg elementów. Jako zbiór uporządkowany, dostarcza metody first() i last() zwracające najmniejszy i największy element.
Interfejs Set - ciąg dalszyInterfejs Set - ciąg dalszy
LinkedHashSet:
Cechuje się taką samą szybkością dostępu jak hashSet, z tym, że LinkedHashSet zachowuje oryginalną kolejność dodawania elementów. Klasa ta oparta jest na LinkedList. Wyniki pobierane są w kolejności jakiej były dodawane do kontenera.
Każdy typów zbioru Set przechowuje elementy w innej kolejności:
W zbiorach HashSet, TreeSet i LinkedHashSet zamieszczone zostały elementy od 0 do 9. Po wypisaniu tych zbiorów otrzymamy:
[ 2 , 4 , 9 , 8 , 6 , 1 , 3 , 7 , 5 , 0 ] – HashSet
[ 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] – TreeSet
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] – LinkedHashSet
Przy tworzeniu własnego typu, należy pamiętać o zaimplementowaniu interfejsu Compareble i metody compareTo(), aby zbiór Set mógł określić przynależność jakiegoś elementu do zbioru, oraz aby mógł zbiór posortować (w przypadku TreeSet).
SortedSetSortedSet
Jedyną dostępną implementacją SortedSet jest klasa TreeSet. W związku z powyższym, TreeSet dostarcza metody interfejsu SortedSet:
Comparator comparator(); /* Zwraca interfejs Comparator, lub null dla domyślnego comparatora */
Object first() ; // Podaje najmniejszy element
Object last(); // Podaje największy element
SortedSet subSet(odElementu, doElementu); /* zwraca fragment zbioru obejmujący element odElementu, do elementu doElementu */
SortedSet headSet(doElementu); /* Zwraca fragment zbioru o elementach mniejszych od elementu doElementu */
SortedSet tailSet(odElementu); /* Zwraca fragment zbioru o elementach większych od elementu odElementu */
Interfejs MapInterfejs Map
Kontener Map pozwala na przechowywanie par elementów {klucz, obiekt}. Interfejs Map dostarcza kilka podstawowych metod do obsługi tego rodzaju kontenerów:
put(Object klucz, Object wartość); // dodaje wartość i wiąże ją z kluczem
get(Object klucz); // zwraca wartość związaną z kluczem
containsKey(); // sprawdza czy odwzorowanie zawiera klucz
containsValue(); // sprawdza czy odwzorowanie zawiera wartość;
Odwzorowania Map do wyszukiwania elementów wykorzystują metodę hashCode() obiektu przechowywanego, przez co wyszukiwanie elementów w odwzorowaniach Map jest szybsze, niż gdyby zastosowana została metoda z ArrayList.
Interfejs Map - typyInterfejs Map - typy
W Javie dostępne są kilka typów odwzorowań Map: HashMap, TreeMap, LinkedhashMap, WeakhashMap oraz IdentityHashMap.
HashMap:
implementacja oparta na tablicy asocjacyjnej (dawniej HashTable). Zapewnia lokalizację i wstawianie par w czasie stałym. Zachowanie może być regulowane, poprzez ustawienie parametrów w konstruktorze.
LinkedHashMap (JDK 1.4):
Implementacja podobna do HashMap, lecz podczas przeglądania pary zwracane są w kolejności wstawiania. Działa trochę wolniej od HashMap. Wstawianie elementów odbywa się szybciej niż w HashMap, dzięki wykorzystaniu listy połączonej.
Interfejs Map – typy – ciąg dalszyInterfejs Map – typy – ciąg dalszy
WeakHashMap:
Odwzorowanie operujące na słabych klucza, umożliwiające usunięcie z pamięci obiektów przechowywanych w mapie. Obiekty bez odwołań są usuwane przez odśmiecacz pamięci, jeżeli w programie nie ma odwołań do nich.
IdentityHashMap (JDK 1.4):
Odwzorowanie hash’ujące określające równość kluczy przy wykorzystaniu operatora == zamiast metody equals(). Nie nadaje się do zastosowań ogólnych.
TreeSet:
Implementacja oparta na drzewach czerwono-czarnych. Pary po umieszczeniu są sortowane według porządku wyznaczonym przez interfejs Comparable. Dzieki posortowaniu dostępne są funkcje firstKey() i lastKey() zwracające najmniejszy i największy z kluczy. Ponadto posiada metodę subMap() pozwalającą uzyskać fragment drzewa.
Interfejs Map Interfejs Map – wydajno– wydajnośćść
Czynniki wydajności HashMap:
pojemność – liczba komórek tablicy
pojemność początkowa – liczba komórek tablicy po jej stworzeniu
rozmiar – liczba pozycji znajdujących się obecnie w tablicy
współczynnik zapełnienia – 0 oznacza pustą tablicę, 1 pełną (rozmiar/pojemność). Współczynnik ten oznacza, że gdy kontener osiągnie ten współczynnik zapełnienia, to automatycznie zwiększy swój rozmiar (pojemność).
Powyższe współczynniki można ustawiać w konstruktorze, w celu zmiany zachowania odwzorowania.
SortedMapSortedMap
Jedyną dostępną implementacją SortedMap jest klasa TreeMap. W związku z powyższym, TreeMap dostarcza metody interfejsu SortedMap:
Comparator comparator(); /* Zwraca interfejs Comparator, lub null w przypadku domyślnego comparatora*/
Object firstKey() ; // Podaje najmniejszy klucz
Object lastKey(); // Podaje największy klucz
SortedMap subMap(odKlucza, doklucza); /* zwraca fragment odwzorowania obejmujący klucze odKlucza, do klucza doKlucza */
SortedMap headMap(doKlucza); /* Zwraca fragment odwzorowania o kluczach mniejszych od klucza doKlucza */
SortedMap tailMap(odKlucza); /* Zwraca fragment odwzorowania o kluczach większych od klucza odKlucza */
Hash’owanieHash’owanie Każdy obiekt domyślnie dziedziczy po klasie Object, jeżeli nie określimy
klasy bazowej. Dlatego też każdy obiekt dziedziczy metodę hashCode() klasy Object, zwracającą adres danego obiektu.
Aby można było korzystać z odwzorowań dla własnych obiektów, należy zaimplementować metodę equals() i interfejs Comparable, a także metodę hashCode() (chyba, że chcemy skorzystać z domyślnej metody klasy Object).
Powinno się za każdym razem przesłaniać metodę hashCode(), w celu uzyskania poprawnego działania kontenerów opartych na działaniu tej metody.
Przykład:
public putInHash() {
Map map = new HashMap();
int[] tab1 = {1, 2};
int[] tab2 = {2, 1};
map.put(tab1, new Object());
map.put(tab2, new Object()); }
Różne dla equals()
Takie samo dla hashCode()
Hash’owanie przykład kolejnyHash’owanie przykład kolejny
public putInHash() {
public class MyKey {
int field1;
int field2;
MyKey(int f1, int f2) {
field1 = f1;
field2 = f2;}
Map map = new HashMap();
MyKey k1 = new MyKey(1, 2);
MyKey k2 = new MyKey(2, 1);
map.put(k1, new Object());
map.put(k2, new Object()); }
różne dla equals()
Takie samo dla hashCode()
Jak poprzednio:
hashCode() - przykładhashCode() - przykładpublic class TShirt {
int ID; //number on tshirt
int size; // size of tshirt
String desc; // description
public TShirt(int id, int s, String d) {
ID = id;
size = s;
description = d; }
public int hashCode() { return ID; };
public boolean equals(Object o) {
return ( desc.equals(((TShirt) o).desc)
&& size == ((TShirt) o).size); }
}
public class PList{
String[] players = {”p1”, ”p2”};
TShirt ts1 = new TShirt(1, 7, ”player’s 1 shirt”);
TShirt ts2 = new TShirt(2, 7, ”player’s 1 shirt”);
public Plist() {
Map map = new HashMap();
map.put(ts1, players[0]);
map.put(ts2, players[1]);
};
}
Dodatkowe usługi klasy CollectionsDodatkowe usługi klasy Collections
max(Collection) – zwraca maksymalny element, stosuje normalną metodę porównania dla obiektów w strukturze
min(Collection) – jak wyżej, lecz zwraca element minimalny
max(Collection,Comparator) – j.w. stosuje Comparator do porównań
min(Collection,Comparator) – analogicznie do powyższego
indexOfSublist(List Source, List Target) – podaje indeks pierwszego miejsca, w którym Target występuje w Source
lastOfSublist(List Source, List Target) – analogicznie do powyższego
replaceAll(List list, Object old, Object new) – zamienia old na new w liscie
reverse(List) – odwracanie kolejności występowania
rotate(List list, int dist) – przesuwa elementy listy o dystans dist
copy(List target, List source) – kopiuje elementy z source do taget
swap(List list, int i, int j) – zamienia położenie elementów i i j
Dodatkowe usługi klasy CollectionsDodatkowe usługi klasy Collections
nCopies(int n, Object o) – zwraca niemodyfikowalną listę rozmiaru n, której wszystkie odwołania wskazują na obiekt o
Enumeration(Collection) – zwraca obiekt Enumeration dla podanego argumentu
List(Enumeration e) – Zwraca obiekt ArrayList wygenerowany przy użyciu podanego obiektu Enumeration
SynchronizacjaSynchronizacja
Kolekcje mogą być obsługiwane przez kilka wątków jednocześnie, co z kolei wymaga, aby ta kolekcja była w jakiś sposób synchronizowana.
Klasa Collections udostępnia sposób automatycznej synchronizacji całego kontenera. Dzięki temu nie ma sposobności przypadkowego udostępnienia wersji niezsynchronizowanej.
Przykłady:
Set s = Collections.synchronizedSet(new HashSet());
List l = Collections.synchronizedList(new ArrayList());
Map m = Collections.synchronizedMap(new HashMap());
W powyższych przypadkach, nowy kontener jest natychmiast przekazywany do odpowiedniej metody synchronizującej.
fail-fastfail-fast
Kontenery w Javie posiadają również zabezpieczenie przed modyfikacją ich zawartości przez więcej niż jeden proces.
Mechanizm fail-fast wyszukuje wszystkie zmiany kontenera, nie pochodzące od danego procesu. Jeżeli inny proces modyfikuje kontener, spowoduje to pojawienie się wyjątku ConcurrentModificationException.
Przykład:
public class MyClass {
public static void main(String[] args) {
Collection c = new ArrayList();
Iterator it = c.interator();
c.add(”My object”);
}
Spowoduje pojawienie się wyjątku
ConcurrentModificationException
KoniecKoniec
„To już jest koniec.
Nie ma już nic.
Jesteśmy wolni. (?)
Możemy iść.” (???)