Kolekcje w Javie.
Kolekcja - obiekt umożliwiający przechowywanie i przetwarzanie wielu obiektów ( elementów kolekcji). W przeciwieństwie do tablic jej rozmiar może się zmieniać i jej elementami mogą być tylko obiekty ( referencje).
Pełny opis hierarchii klas kolekcyjnych można znaleźć w helpie ( Java Collections Framework - JFC). Opis ten jest zbudowany na trzech poziomach abstrakcji :
interfejsy ( wymagany zestaw metod)
klasy abstrakcyjne ( częściowa implementacja metod wspólnych)
klasy konkretne ( implementacja)
Ja przedstawiam tylko minimalny zestaw informacji umożliwiający wykorzystanie podstawowych rodzajów kolekcji.
Definicje klas kolekcyjnych znajdują się w pakiecie java.util ( trzeba dodać import java.util.*;).
Java definiuje dwa drzewa interfejsów kolekcyjnych :
Iterable<E>
Collection<E>
List<E>
Set<E>
SortedSet<E>
i Map<K,V>
SortedMap<K,V>
Iterable - zawiera tylko konstruktor klasy Iterator<E>
Collection<E> - metody wspólne dla wszystkich kolekcji np.
Boolean isEmpty();
int size();
boolean add(E e); // true jeśli wstawiono element
boolean addAll( Collection <? extends E> c) // true jeśli dodano choć jeden element
boolean contains(Object o) // true gdy istnieje taki e , że o==null? e==null: o.equals(e)
boolean containsAll(Collection <?> c )
boolean remove(Object o) //usuwa tylko jedno wystąpienie
boolean removeAll(Collection<?> c) //usuwa wszystkie wystąpienia każdego obiektu
void clear()
boolean retainAll(Collection<?> c) //część wspólna kolekcji
E[] toArray() // zapis elementów kolekcji w tablicy
Przetwarzanie wszystkich elementów kolekcji :
pętla foreach
for( E el : c) //c wyrażenie typu kolekcyjnego
instrukcja;
użycie iteratora // można stosować również do pełnych tablic
public interface Iterator<E>
{ boolean hasNext(); // czy jest następny element
E next(); // daj następny element
void remove( ); //usuń element zwrócony ostatni przez iterator
}
Realizacja foreach za pomocą iteratora :
for(Iterator<E> it = c.iterator(); it.hasNext();)
{ E el=it.next();
instrukcja;
} // można użyć while
List<E> - sekwencja, ciąg; wartości elementów mogą się powtarzać , elementy są uporządkowane ( ale nie muszą być posortowane). Jest to odpowiednik dynamicznej tablicy.
E get(int index)
List<E> subList(int poc, int kon) //od poc do kon-1
int indexOf(Object O)
int lastIndexOf(Object O)
void add(int indeks, E elem) // bez indeksu - na koniec
E set(int indeks,E elem) // zamień, wynik - stary element
E remove(int indeks)
ListIterator<E> listIterator( )
Set<E> - odpowiednik zbioru matematycznego; elementy się nie powtarzają i nie są uporządkowane
nie udostępnia nowych metod
SortedSet<E> - elementy nie powtarzają się i są posortowane; kolejność naturalna - wyznaczona przez compareTo lub odpowiedni komparator - elemety muszą realizować interfejs Comparable lub być akceptowane przez odpowiedni Comparator;
E first() // zwraca pierwszy ( najmniejszy element)
SortedSet<E> headSet( E to Element ) // elementy mniejsze od wskazanego
E last() // ostatni
SortedSet<E> subSet(E fromElement, E toElement)
SortedSet<E> tailSet(E fromElement) // większe lub równe
Map<K,V> - odwzorowanie,słownik, tablica asocjacyjna, mapa. Zbiór par klucz ( typu K ) i warość (typu V). Może być traktowane jako tablica indeksowana kluczami.
Oczywiście klucze nie mogą się powtarzać.
boolean containsKey(Object key)
boolean containsValue(Object value)
V get(Object key)
Set<Map.Entry<K,V>> entrySet( )//zbiór par
Set<K> keySet()
Collection<V> values()
V put( K key, V value) // wstaw maplet, wynik - stara wartość lub null
void putAll(Map<? extends K, ? extends V> m) // złożenie odwzorowań
SortedMap<K,V> - odwzorowaniowy odpowiednik zbioru uporządkowanego według wartości kluczy;
K firstKey()
SortedMap<K,V> headMap(K toKey)
K lastKey()
SortedMap<K,V> subMap(K fromKey, K toKey)
SortedMap<K,V> tailMap(K fromKey)
Klasy abstrakcyjne ( zawierają implementacje niektórych ogólnych metod )
Szczegóły są zawarte w dokumentacji.
Klasy konkretne :
ArrayList<E> - podstawowa realizacja listy - odpowiednik tablicy dynamicznej ( o zmiennym rozmiarze)
void trimToSize() //dopasowuje rozmiar tablicy do rozmiaru listy
LinkedList<E> - realizacja listy w postaci dwukierunkowej prostej listy dowiązaniowej; dodano wersje metod : get, set i remove działające na początku (First) i końcu (Last) listy.
HashSet<E> - szybka realizacja zbioru w postaci tablicy haszowanej, elementu są nieuporządkowane, null może być elementem zbioru
Object clone( ) //tworzy kopię zbioru, elementy nie są kopiowane
TreeSet<E> - realizacja zbioru w postaci tablicy drzewa czerwono-czarnego, elementu są posortowane
Object clone( ) //tworzy kopię zbioru, elementy nie są kopiowane
HashMap<K,V> - podstawowa realizacja odwzorowania w postaci tablcy haszowanej; nie ma dodatkowych metod
TreeMap<K,V> - realizacja w postaci drzewa czerwono-czarnego uporządkowanego według wartości kluczy; nie ma dodatkowych metod.
Przykład przetwarzania kolekcji i przeciążeniach odpowiednich metod dla elementów kolekcji :
import java.util.*;
import java.io.*;
public class ComparatorPublikacji implements Comparator<Publikacja>,Serializable
{ public int compare(Publikacja p1,Publikacja p2)
{ return p1.autor.compareTo(p2.autor)!=0 ? p1.autor.compareTo(p2.autor)
: p1.tytul.compareTo(p2.tytul);}
}
import java.io.*;
public abstract class Publikacja implements Comparable, Cloneable, Serializable
{ String tytul;
String autor;
int rok;
Publikacja(String tytul, String autor, int rok)
{this.tytul=tytul; this.autor=autor;this.rok=rok;
}
public Publikacja clone()
{ try{ Publikacja p=(Publikacja)super.clone();
p.tytul= new String(tytul);
p.autor=new String(autor);
return p;
} catch(CloneNotSupportedException e){return null;}
}
public String toString()
{ return tytul+" "+ autor+" " +rok +" "; }
public boolean equals(Publikacja p)
{ return p!=null && tytul.equals(p.tytul) && autor.equals(p.autor) ; }
public int hashCode()
{ return tytul.hashCode() & autor.hashCode(); }
public int compareTo(Object p1)
{ Publikacja p=(Publikacja)p1;
return (tytul.compareTo(p.tytul)!=0 ? tytul.compareTo(p.tytul)
: autor.compareTo(p.autor));
}
}
public class Ksiazka extends Publikacja
{ String wydawnictwo;
public Ksiazka(String tytul, String autor,int rok, String wydawnictwo)
{ super(tytul,autor,rok);
this.wydawnictwo=wydawnictwo;
}
public String toString()
{ return super.toString() + wydawnictwo;}
}
public class Artykol extends Publikacja
{ String czasopismo;
public Artykol(String tytul, String autor,int rok, String czasopismo)
{super(tytul,autor,rok);
this.czasopismo=czasopismo;
}
public String toString()
{ return super.toString() + czasopismo;}
}
import java.util.*;
public class test
{ Publikacja[] pub ={new Ksiazka("Podstawy","Jan",1980,"Iskry"),
new Artykol("Java","Tom",2008,"Algorytmy")};
SortedSet<Publikacja> s = new TreeSet<Publikacja>(Arrays.asList( pub));
public void druk(Collection<Publikacja> s)
{ for(Publikacja el:s)
System.out.println(el+" , ");
System.out.println();
}
public void druk1(Iterator<Publikacja> it)
{ while(it.hasNext())
System.out.println(it.next()+" , ");
System.out.println();
}
public void test()
{ druk(s);
druk1(s.iterator());
System.out.println(s);
Ksiazka k1=new Ksiazka("Podstawy","Jan",1980,"Iskry");
Ksiazka k2=new Ksiazka("Podstawy","Jan",1999,"Iskry2");
Ksiazka k3=new Ksiazka("Podstawy","Janusz",1980,"Iskry");
System.out.println( s.add(k1));
System.out.println( s.contains(k1));
System.out.println( s.add(k2));
System.out.println( s.contains(k2));
System.out.println( s.contains(k3));
System.out.println( s.add(k3));
druk(s);
System.out.println(k1);
Comparator<Publikacja> comp=new ComparatorPublikacji();
SortedSet<Publikacja> s1 = new TreeSet<Publikacja>(comp);
s1.addAll(Arrays.asList(pub));
druk(s1);
}
}