object that groups multiple elements into a single unit
Kolekcje
W wielu programach deklaracje typu:
MyObject myReference;
są uprawnione, jednak często zwłaszcza przy bardziej skomplikowanych programach nowe obiekty są kreowane w oparciu o pewne kryteria znane dopiero w czasie wykonania. Wcześniej nie jest znana ani liczba, a niekiedy nawet typ
potrzebnych obiektów.
W pewnym stopniu problem rozwiązuje
wbudowany w Javie typ array.
Tablica (Array) to po prostu sekwencja obiektów lub wartości typu prostego opatrzona wspólną nazwą.
Wszystkie elementy tablicy muszą być tego samego typu! Tablice definiujemy uŜywając nawiasów
prostokątnych []:
int[] a1; // zapis naturalny: a1 jest typu tablica int lub
int a1[]; // styl języka C
Tablice
Alokacja elementów tablicy
Nie zaalokowano jeszcze miejsca dla tablicy, a1 jest referencją do tablicy.
MoŜna to zrobić za pomocą wyraŜenia inicjalizującego:
int[] a1 = { 1, 2, 3, 4, 5 };
int[] a1 = new [11] ; // The primitives inside //the array are automatically initialized to zero
Weeble[] a;
a = new Weeble[] { new Weeble(), new Weeble() };
Tablice posiadają nieodłączne pole składowe length, które moŜna odczytywać (ale nie zmieniać) wskazujące ile
elementów jest w tablicy (a1.length jest równe 5). Indeks tablicy zmienia się od 0 do length-1. Wyjście poza ten zakres generuje błąd czasu wykonania (exception).
Kontrola indeksów tablic jest jednym z powodów mniejszej efektywności środowiska Java, pozwala
natomiast uniknąć wielu nieprzewidzianych i trudnych do wykrycia błędów programu.
Uwaga: tablica jest obiektem, nawet jeśli elementy tablicy są typu prostego.
Kontrola indeksów
Object[] a; // uninitialized variable
Object[] b = new Object[5]; // Null references for(int i; i < b.length; i++)
b[i] = new Object() ;
Tablice wielowymiarowe
int[][] a1 = { { 1, 2, 3, }, { 4, 5, 6, }, };
int[][][] a2 = new int[2][2][4];
Klasa Arrays
W pakiecie java.util znajduje się klasa Arrays, w której zdefiniowano szereg uŜytecznych metod statycznych. Są to cztery następujące przeciąŜone (dla typów prostych i Object) grupy:
equals( ), - do porównania zawartości tablic;
fill( ), do wypełnienia tablicy określoną wartością (taka sama) sort( ), do sortowania tablic;
binarySearch( ), wyszukanie elementu w posortowanej tablicy.
Ponadto metoda asList( ) umieszcza elementy tablicy w kontenerze List.
W klasie System zdefiniowano uŜyteczną
metodę słuŜącą do kopiowania zawartości tablic:
void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Kopiowanie zawartości tablic
int[] i = new int[7];
int[] j = new int[10];
Arrays.fill(i, 47);
Arrays.fill(j, 99);
System.arraycopy(i, 0, j, 0, i.length); // "j = //[47, 47, 47, 47, 47, 47, 47, 99, 99, 99]„
Oczywiście kaŜde naruszenie zakresu indeksów spowoduje wygenerowanie wyjątku.
Dla tablic obiektów kopiowane są tylko referencje nie same obiekty!
Przykład
Porównywanie tablic metoda Arrays.equals()
Aby tablice były równe musza mieć taką samą liczbę elementów oraz odpowiadające sobie elementy muszą być równe w sensie metody equals() typu tych
elementów, a dla typów prostych w sensie metody
equals() odpowiednich typów opakowujących.
Porównywanie elementów tablic.
Jednym z podstawowych celów projektowania
programów jest „separacja rzeczy, które się zmieniają od tych, które są niezmienne”.
Jako przykład rozwaŜmy problem sortowania. To co jest niezmienne to sam algorytm sortowania, natomiast zmienny jest sposób porównywania obiektów. Stąd
zamiast wbudowywać te sposoby porównywania w
róŜne procedury sortowania stosujemy rozwiązanie, w
którym niezmienny fragment kodu wywołuje zmienną
część (technika callback).
Java oferuje dwa sposoby porównywania obiektów.
Pierwszy oparty jest na metodzie wprowadzonej do klasy drogą implementacji interfejsu java.lang.Comparable. Interfejs ten definiuje tylko jedną metodę: int compareTo(Object o).
Metoda ta porównuje przekazany argumentem obiekt i zwraca wartość mniejszą od zera jeśli bieŜący obiekt jest mniejszy od argumentu, zero jeśli oba obiekty są równe i wartość dodatnią jeśli obiekt jest większy od argumentu.
Od implementacji metody compareTo() zaleŜy „co to oznacza, Ŝe obiekt jest mniejszy, równy, większy”. Jeśli klasa
implementuje interfejs Comparable moŜna posortować tablicę obiektów a:
2 sposoby porównywania
public class CompType implements Comparable { int i; int j;
public CompType(int n1, int n2) { i = n1;
j = n2;
}
public String toString() {
return "[i = " + i + ", j = " + j + "]"; } public int compareTo(Object rv) {
int rvi = ((CompType)rv).i;
return (i < rvi ? -1 : (i == rvi ? 0 : 1));
} }
CompType[] a = new CompType[12] ; // …
Arrays.sort(a);
Co jeśli klasa nie implementuje interfejsu Comparable, lub
implementacja nas nie satysfakcjonuje? Rozwiązaniem moŜe być zastosowanie wzorca projektowego strategy, zgodnie z którym zmienny kod umieszczany jest w oddzielnej klasie (strategy
object). Następnie do niezmiennej części algorytmu przekazujemy ten obiekt, który umoŜliwia rozwiązanie problemu. Zgodnie z tym wzorcem moŜemy zaprojektować róŜne sposoby porównywania obiektów i uzupełniać nimi niezmienny algorytm. Przy sortowaniu definiujemy klasy implementujące interfejs Comparator, w
którym zdefiniowano metody: compare( ) i equals( ). PoniewaŜ implementację metody equals( ) wszystkie klasy dziedziczą po klasie Object niezbędne jest jedynie zdefiniowanie metody
compare( ).
2 sposób
Podsumowując, sortowanie tablic zawierających obiekty jest moŜliwe jeśli implementują one interfejs Comparable lub posiadają skojarzony z nim
Comparator.
W obecnych wersjach API języka Java (od 1.2) klasa String implementuje interfejs Comparable co umoŜliwia leksykograficzne sortowanie tablic
stringowych (z uwzględnieniem wielkości liter).
Jeśli ta reguła sortowania nie jest adekwatna do danego
zastosowania to definiujemy własną klasę komparatora np.
public class AlphabeticComparator implements Comparator {
public int compare(Object o1, Object o2) { String s1 = (String)o1;
String s2 = (String)o2;
return s1.toLowerCase().compareTo(s2.toLowerCase());
} }
Searching a sorted array
Once an array is sorted, you can perform a fast search for a
particular item by using Arrays.binarySearch( ). However, it’s very important that you do not try to use binarySearch( ) on an unsorted array; the results will be unpredictable.
Arrays.binarySearch( ) produces a value greater than or equal to zero if the search item is found. Otherwise, it produces a
negative value representing the place that the element should be inserted if you are maintaining the sorted array by hand. The value produced is
-(insertion point) - 1
Podsumowując tablice są podstawowym i
najefektywniejszym sposobem przechowywania
grupy obiektów (i jedynym sposobem dla typów prostych). Jeśli jednak nie jest znana z góry liczba obiektów lub potrzebujemy bardziej wyrafinowanego sposobu przechowywania obiektów naleŜy skorzystać z biblioteki klas kontenerowych (Collections).
Pakiet utilities zawiera zbiór klas kontenerowych
znanych jako kolekcje. Kontenery te (List, Set, Map) mogą przechowywać wyłącznie typy obiektowe!
Wartości typu prostego naleŜy przed umieszczeniem w kontenerze „opakować” (klasy Integer, Double, etc.).
Podsumowanie
Interfejsy „kolekcyjne”
public interface Collection<E> extends Iterable<E>
{
// Basic operations int size();
boolean isEmpty();
boolean contains(Object element);
boolean add(E element); //optional
boolean remove(Object element); //optional Iterator<E> iterator();
void clear(); //optional
...