Seminarium 2 Introduktion till Java Collections Framework Innehåll Generik Bakgrund Generik används för att få typsäkra datastrukturer Java Collections Framework Standardbibliotek med datastrukturer i Java, exempelvis ArrayList, LinkedList, etc. interfacen Iterator och Iterable och foreach-sats i Java - används för att traversera genom en samling element Jämföra objekt metoden equals, interfacet Comparable Efter detta seminarium ska ni kunna lösa uppgifterna i kapitel 3 i övningshäftet. Typosäkerhet utan generik! I den gamla modellen kunde man skriva: mylist.add(new Integer(1)); mylist.add(new Integer(2)); mylist.add(new Person( Kalle )); Om avsikten är att listan ska innehålla tal, har vi gjort fel på rad 3. Kompilatorn kan inte upptäcka detta koden är korrekt, både Integer och Person är subklasser till Object. PFK (Seminarium 2 JCF) HT 2016 1 / 38 Generik i Java PFK (Seminarium 2 JCF) HT 2016 2 / 38 Exempel på en generisk klass java.util.arraylist Kompilatorn kommer att upptäcka typfel. Ex: ArrayList<Integer> mylist = new ArrayList<Integer>(); mylist.add(new Person("Kalle")); ger nu kompileringsfel, mylist får enligt sin deklaration endast innehålla objekt av typen Integer. Utdrag ur den generiska klassen java.util.arraylist: public class ArrayList<E> { public ArrayList() { public boolean add(e x) { public void add(int index, E x) { public E get(int index) { Alla add-metoder har inparameter av typen E. Därför kan enbart objekt av klassen E (eller subklasser till denna) sättas in i listan. PFK (Seminarium 2 JCF) HT 2016 3 / 38 PFK (Seminarium 2 JCF) HT 2016 4 / 38
Implementering av generisk klass Generisk klass med flera typparametrar Implementering Java 1.4 public class Container { private Object item; public Container(Object x) { item = x; public Object get() { return item; Fr o m Java 5.0 generisk klass public class Container<E> { private E item; public Container(E x) { item = x; public E getitem() { return item; public class Pair<K, V> { private K key; private V value; public Pair(K key, V value) { this.key = key; this.value = value; public V getvalue() { return value; public void set(object x) { item = x; public void setitem(e x) { item = x; public void setvalue(v val) { value = val; PFK (Seminarium 2 JCF) HT 2016 5 / 38 Generisk klass med flera typparametrar Användning PFK (Seminarium 2 JCF) HT 2016 6 / 38 Generiska interface Även interface kan vara generiska. Ex: Exempel: Pair<String, Integer> pair = new Pair<String, Integer>("June", 30); int nbrdays = pair.getvalue(); public interface Set<E> { boolean add(e x); int size(); boolean contains(object x); PFK (Seminarium 2 JCF) HT 2016 7 / 38 PFK (Seminarium 2 JCF) HT 2016 8 / 38
Generik syntax Deklaration av parametriserade (generiska) klasser/interface: public class Set<E> { public interface Comparable<T> public class Pair<K,V> Klassen/interfacet har en parameterlista som omges av tecknen < och >. En parameter namnges med en typvariabel (markeras ovan) som kan vara en godtycklig identifierare. Om det är flera parametrar används komma som skiljetecken. PFK (Seminarium 2 JCF) HT 2016 9 / 38 Restriktioner för typparametrar och typvariabler Parameter till generisk klass kan inte vara primitiv typ: SomeClass<int> c = // Går inte! Typvariabler kan inte användas för att skapa objekt: Generik syntax I generiska klasser/interface kan typparametrarna användas för att deklarera attribut, variabler, Ex: public class Container<E> { private E item; public Container(E x){ this.item = x; public E getitem()){ return item; Man kallar ofta E för typvariabel när den används så här. PFK (Seminarium 2 JCF) HT 2016 10 / 38 Generisk klass Övning generisk klass Övning public class ArrayCollection<E> { private E[] thecollection = (E[]) new Object[10]; private int size = 0; public class SomeClass<E> { public void p() { E x = new E(); // Fel! Typparametrar kan inte användas för att överlagra metoder: public class MyClass<T,U> { public void p(t x) { public void p(u x) { // Fel! public boolean add(e x) { if (size == thecollection.length) { // Dubblera arrayn thecollection[size] = x; size++; return true; public boolean contains(object x) { // ÖVNING: Implementera PFK (Seminarium 2 JCF) HT 2016 11 / 38 PFK (Seminarium 2 JCF) HT 2016 12 / 38
Typparametrar med begränsningar JCF Java Collections Framework Ibland behöver man ange begränsning på typparmetern: public class ASortedCollection<E extends Comparable<E>> <E extends T> betyder: E måste vara subklass till T om T är en klass. Det är också tillåtet att E = T. E måste implementera interfacet T om T är ett interface. I exemplet ovan anger vi alltså att E måste vara en typ som implementerar interfacet Comparable<E>. Vi kan därmed använda metoden compareto på objekt av typen E i implementeringen av ASortedCollection. Är en hierarki av interface, abstrakta klasser och konkreta klasser för samlingar av element. Finns i paketet java.util. Basen i hierarkin är ett interface Collection: interface Collection<E> { boolean add(e x); boolean contains(object x); boolean remove(object x); boolean isempty(); int size(); interfacen Iterator och Iterable och foreach-sats i Java - används för att traversera genom en samling element PFK (Seminarium 2 JCF) HT 2016 13 / 38 JCF interface hierarki PFK (Seminarium 2 JCF) HT 2016 14 / 38 JCF interface hierarki Queue Collection List Set SortedSet Map SortedMap Dokumentation På Javas hemsida (länk finns på kursens hemsida) finns dokumentation av Javas standardklasser. Där finns även tutorials, bl.a. om Javas Collection-klasser. PFK (Seminarium 2 JCF) HT 2016 15 / 38 Collection en samling av element Queue en samling av element som utgör en kö List en samling element där positionering är möjlig (första, sista, element på plats i, ) Set en samling element där dubbletter är förbjudna SortedSet som Set men med krav att elementen går att jämföra Map en samling av element, där varje element har en en nyckel och ett värde (jfr. lexikon) SortedMap som Map men med krav att nycklarna går att jämföra PFK (Seminarium 2 JCF) HT 2016 16 / 38
JCF några klasser Iteratorer Interface Queue List Set SortedSet Map SortedMap Implementering LinkedList, PriorityQueue ArrayList, LinkedList HashSet TreeSet HahsMap TreeMap Antag att vi lagrar ett antal personer i en lista (eller i någon annan samlingsklass): ArrayList<Person> plist = new ArrayList<Person>(); // här sätts Person-objekt in i samligen Hur ska vi göra för iterera genom samligen och behandla alla personerna (t.ex. skriva ut alla personernas namn)? PFK (Seminarium 2 JCF) HT 2016 17 / 38 Interfacet Iterable<E> PFK (Seminarium 2 JCF) HT 2016 18 / 38 Interfacet Iterator<E> I Java finns följande interface: public interface Iterable<E> { /** Returns an iterator over a set of elements of type E */ Iterator<E> iterator(); Interfacet Collection ärver interfacet Iterable: En instans av en klass som implementerar interfacet Iterator används för att iterera över alla element i en samling. public interface Iterator<E> { /** Returns true if the iteration has more elements. */ boolean hasnext(); /** Returns the next element in the iteration. */ E next(); public interface Collection<E> extends Iterable<E> Alla klasser som implementerar Collection måste alltså implementera metoden iterator(). /** Removes from the underlying collection the last element returned by the iterator (optional). */ void remove(); PFK (Seminarium 2 JCF) HT 2016 19 / 38 PFK (Seminarium 2 JCF) HT 2016 20 / 38
JCF interface hierarki med Iterable<E> och Iterator<E> Användning av iterator Exempel Iterable Här används en iterator för att traversa en lista: iterator() Collection Iterator hasnext() next() remove() Map SortedMap ArrayList<Person> plist = new ArrayList<Person>(); // här sätts Person-objekt in i samlingen Iterator<Person> itr = plist.iterator(); while (itr.hasnext()) { Person p = itr.next(); // behandla p Queue List Set SortedSet Lägg märke till hur man skaffar sig en iterator genom att anropa metoden iterator. PFK (Seminarium 2 JCF) HT 2016 21 / 38 Metoden iterator() Exempel på collection-klass med metoden iterator PFK (Seminarium 2 JCF) HT 2016 22 / 38 Implementering av interfacet Iterator<E> Exempel: Klassen ArrayIterator Nu ska vi implementera en iterator! public class ArrayCollection<E> implements Collection<E> { private E[] thecollection; private int size; impl av konstruktor, add, public Iterator<E> iterator() return new ArrayIterator(); private class ArrayIterator implements Iterator<E> {. implementering på nästa bild private class ArrayIterator implements Iterator<E> { private int pos; private ArrayIterator() { pos = 0; public boolean hasnext() { return pos < size; PFK (Seminarium 2 JCF) HT 2016 23 / 38 PFK (Seminarium 2 JCF) HT 2016 24 / 38
Implementering av interfacet Iterator<E> Exempel: Klassen ArrayIterator, forts Implementering av interfacet Iterator<E> Inre klass public E next() { if (hasnext()) { E item = thecollection[pos]; pos++; return item; else { throw new NoSuchElementException(); public void remove() { throw new UnsupportedOperationException(); Den klass som implementerar interfacet Iterator kan vara inre klass i den klass som representerar samlingen. En inre klass har tillgång till alla attribut i den omgivande klassen det utnyttjas t.ex. i operationen next. Den kan vara privat, och ha en en privat konstruktor, eftersom det bara är den omgivande klassen som skapar instanser. Metoderna hasnext, måste däremot vara publika eftersom interfacet Iterator föreskriver detta. PFK (Seminarium 2 JCF) HT 2016 25 / 38 Implementering av interfacet Iterator<E> Kommentar PFK (Seminarium 2 JCF) HT 2016 26 / 38 foreach-sats i Java Exempel Implementeringen som visats här är förenklad: Iteratorer har enligt sitt kontrakt inte till uppgift att klara av att samlingen modifieras mellan anrop av next(). En korrekt iterator-implementering måste upptäcka detta och generera en exception om samlingen modifieras. ArrayList<Person> plist = new ArrayList<Person>(); // här sätts Person-objekt in samlingen for (Person p : plist) { // behandla p Ett sätt att enkelt iterera över samlingar. Man slipper att explicit använda en iterator. for (Person p : plist) kan läsas som för varje p i plist. Kan användas för objekt av klasser som implementerar Iterable och för vektorer. PFK (Seminarium 2 JCF) HT 2016 27 / 38 PFK (Seminarium 2 JCF) HT 2016 28 / 38
foreach-sats Vektorer Kan också användas för att iterera över elementen i en vektor. Ex: En metod som skriver ut namn på personer som lagrats i en vektor av typ Person[]: public void print(person[] a) { for (Person p : a) { System.out.println(p.getName()); Iterator foreach-sats Övning Övning Antag att vi har följande lista: LinkedList<Integer> list = new LinkedList<Integer>(); list.add(25); list.add(42); Summera talen i list genom att använda iterator() resp. foreach-sats. PFK (Seminarium 2 JCF) HT 2016 29 / 38 foreach-sats Begränsningar PFK (Seminarium 2 JCF) HT 2016 30 / 38 Söka efter objekt i en lista Följande klass beskriver en person: Foreach-sats kan inte användas när man explicit behöver tillgång till iteratorn i koden. Exempel: Tag bort alla personer som matchar x ur en ArrayList<Person> plist: Iterator<Person> itr = plist.iterator(); while (itr.hasnext()) { if (itr.next().equals(x)) { itr.remove(); Här behövs iteratorn för att kunna ta bort element. public class Person { private String name; private int idnbr; public Person (String name, int idnbr) { this.name = name; this.idnbr = idnbr; Vad skrivs ut när följande rader exekveras? ArrayList<Person> list = new ArrayList<Person>(); list.add(new Person("Kalle", 1)); list.add(new Person("Kajsa", 2)); System.out.println(list.contains(new Person("Kalle", 1))); PFK (Seminarium 2 JCF) HT 2016 31 / 38 PFK (Seminarium 2 JCF) HT 2016 32 / 38
Jämföra likhet Metoden equals Omdefiniera equals med instanceof Metoden equals används för att jämföra om två objekt är lika: Person p1 = ; Person p2 = ; if (p1.equals(p2)) { Metoden equals finns i superklassen Object. Om metoden inte skuggas så jämförs referenser, dvs, om det är samma objekt. Om man istället vill att innehållet inuti objekten ska jämföras måste man omdefiniera (skugga) equals. Exempel: Om man vill att två personer ska anses lika när de har samma id-nummer måste man omdefiniera equals i klassen Person. public boolean equals(object obj) { if (obj instanceof Person) { return idnbr == ((Person) obj).idnbr; else { return false; Observera att parametern till equals måste vara av typ Object, annars blir det inte skuggning. Därför måste också typomvandling till Person ske när man ska använda obj:s idnbr. Uttrycket obj instanceof Person returnerar true om obj:s typ är Person eller någon subklass till Person. Uttrycket obj instanceof Person returnerar false om obj har värdet null. PFK (Seminarium 2 JCF) HT 2016 33 / 38 Interfacet Comparable Specifikation PFK (Seminarium 2 JCF) HT 2016 34 / 38 Implementering av interfacet Comparable Exempel I Java finns ett generiskt interface, Comparable<T>: public interface Comparable<T> { /** * Compares this object with the specified object for order. * Returns a negative integer, zero, or a positive integer as * this object is less than, equal to, or greater than the * specified object. */ public int compareto(t x); Objekt av klasser som implementerar detta interface går att jämföra med varandra och kan t.ex. sorteras. public class Person implements Comparable<Person> { private String name; private int idnbr; public int compareto(person x) { return idnbr - x.idnbr; public boolean equals(object obj) { if (obj instanceof Person) { return compareto((person) obj) == 0; else { return false; PFK (Seminarium 2 JCF) HT 2016 35 / 38 PFK (Seminarium 2 JCF) HT 2016 36 / 38
Jämföra likhet Metoderna compareto och equals Interfacet Comparable innehåller bara metoden compareto. Men för klasser som implementerar interfacet Comparable finns det två sätt att jämföra avseende likhet: Person p1 = ; Person p2 = ; if (p1.compareto(p2) == 0) { if (p1.equals(p2)) { Implementering av interfacet Comparable Övning Övning Ändra klassen Person så att den implementerar interfacet Comparable. Jämförelsen av Person-objekt ska göras med avseende på namnet. public class Person { private String name; private int idnbr; Båda sätten att jämföra ska ge konsistenta resultat. Därför bör metoden equals omdefinieras i klasser som implementerar Comparable. PFK (Seminarium 2 JCF) HT 2016 37 / 38 PFK (Seminarium 2 JCF) HT 2016 38 / 38