Download Sammansatta datatyper Generics: Parametrisk polymorfism – 2016

Document related concepts
no text concepts found
Transcript
Sammansatta datatyper
Generics: Parametrisk polymorfism
[email protected] – 2016
2
Enligt TDDD73:
"Listan är en mycket användbar sammansatt datatyp.
I många andra språk kallar man listor för arrayer."
Många språk har både listor och arrayer!
Exakta definitioner varierar…
Listor (i Java):
Implementerade som klasser
Finns många varianter (olika lagring)
Kan växa och krympa
Arrayer (i Java):
"Inbyggda" i språket
En enda variant
Fixerad storlek
jonkv@ida
Listor och arrayer

4
För varje typ T kan Java dynamiskt skapa motsvarande arraytyp T[]
 Exempel: Object[], String[], Circle[]
 Subklass till Object
▪  Arrayer har metoder och fält, inte bara element
Object
Object[]
String[]
Circle[]
Circle[][]
jonkv@ida
Arrayer 1: Arraytyper
5
numbers
Circle[] circles = new Circle[10];
int[] numbers = new int[rnd()];
Arrayer skapas med new
Storlekar är fasta, men sätts vid körning
int second = numbers[1];
Element hämtas ut med index (första = 0)
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
Index: 0…length-1
Arrayer känner till sin egen längd
int val = numbers[42000];
Indexkontroll: Ger
ArrayIndexOutOfBoundsException
Object
header:
length
[0]
[1]
[41]
(data)
42
0
0
0
Element
initialiseras:
0, 0.0, null,
eller false
jonkv@ida
Arrayer 2: Användning

6
Objektarrayer innehåller pekare:
 Circle[ ] circles = new Circle[10];
circles
Object
header:
length
[0]
[1]
(data)
10
[9]
Kan peka på vilken Circle
som helst, inklusive
subklasser (GraphicCircle)
Element initialiseras till null
Inga nya Circle-objekt skapas!
jonkv@ida
Arrayer 3: Pekar-arrayer

Att initialisera en array
7
Antal element: Implicit
▪ public static void main(String[ ] args) {
int[ ] numbers = new int[ ] { 1, 2, 4, 8, 16 };
print(numbers);
print(new int[ ] { 44, getRandomInt() });
}
Kompileras till kod!
Motsvarar:
int[ ] temp = new int[2];
temp[0] = 44;
temp[1] = getRandomInt();
print(temp);
Kompileras till kod!
Motsvarar:
int[ ] numbers = new int[5];
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 4;
numbers[3] = 8;
numbers[4] = 16;
jonkv@ida
Arrayer 4: Ange element

Arrayer av arrayer:
 Square[ ][ ] board
 Square[ ] row
 Square pos
board
row
= new Square[20][10];
= board[19];
= board[1][0];
Object
header:
length
[0]
[1]
(data)
20
8
Object
header:
length
[0]
…
[9]
Object
header:
length
[0]
…
[9]
(data)
10
(data)
10
[18]
[19]
Object
header:
length
[0]
…
[9]
(data)
10
jonkv@ida
Arrayer 5: Flerdimensionella arrayer

9
Arrayer ärver metoder från Object
 Av historiska anledningar: Bara default-implementationerna
Default-implementationer…
equals() testar identitet
int[ ] ar1 = new int[3]; // 0, 0, 0
int[ ] ar2 = new int[3]; // 0, 0, 0
System.out.println(ar1.equals(ar2));
// false
Kan inte ändras:
Bakåtkompatibilitet!
Vad vi oftast vill
Hjälpmetoder i java.util.Arrays
int[ ] ar1 = new int[3]; // 0, 0, 0
int[ ] ar2 = new int[3]; // 0, 0, 0
System.out.println(Arrays.equals(ar1,ar2));
// true
Också i java.util.Arrays: sort(),
binarySearch(), copyOfRange(),
deepToString(), hashCode(), fill(), …
jonkv@ida
Arrayer 6: Tillgängliga metoder

10
Arrayer ärver metoder from Object
 Av historiska anledningar: Bara default-implementationerna
Default-implementationer…
toString(): typnamn + ID
System.out.println(new int[10].toString());
// [I@3effd44e
System.out.println(new Circle[4]
.toString());
// [LCircle;@2b78146d
Vad vi oftast vill
Hjälpmetoder i java.util.Arrays
System.out.println(
Arrays.toString(new int[10]));
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
jonkv@ida
Arrayer 7: toString()

Styrka: Effektiv användning av minne
11
numbers
 Liten konstant "startkostnad",
12–20 bytes
 Plus elementens "verkliga" kostnad
▪ Kan använda byte / short

Styrka: Snabbt
 Element 40:
Minnesadress = [arraystart+12] + 40 * 4

Svaghet: Kan inte ändra längd när den har skapats!
 Saknar metoder som add(), append(), remove(), …
Object
header:
length
[0]
[1]
[41]
(data)
42
0
0
0
jonkv@ida
Arrayer 8: Styrkor och svagheter

Listor:
 Variabel storlek  bekvämt att använda!
 Inget stöd i språket, men i klassbiblioteken

För bättre förståelser för listor och generics:
 Vi visar en möjlig implementation
 Använder en array internt
 Måste byta ut arrayen när element läggs till
13
jonkv@ida
Listor 1: Intro
14
public class StringList {
private String[] elements;
private int
size;
Använder en array för lagring!
public StringList() {
this.elements = new String[8];
this.size = 0;
}
Allokerar lite extra plats
Hur många av platserna är använda?
StringList strings = new StringList();
strings
Object
header:
elements
size
(data)
0
Object
header:
length
[0]
[1]
[7]
(data)
8
jonkv@ida
Listor 2: En listklass
15
public void add(String element) {
elements[size] = element;
size++;
}
StringList strings = new StringList();
strings.add("Hello");
strings
Object
header:
elements
size
(data)
1
Object
header:
length
[0]
[1]
(data)
8
[7]
Vad händer när arrayen blir full?
"Hello"
jonkv@ida
Listor 3: En listklass (forts.)
public void add(String element) {
if (size == elements.length) {
int newsize = 2*size;
String[] arr2 = new String[newsize];
System.arraycopy(…);
this.elements = arr2;
}
elements[size] = element;
size++;
}
16
Är interna lagringen full?
Skapa större array,
kopiera innehållet,
kasta bort gamla arrayen!
jonkv@ida
Listor 4: En listklass (forts.)
public String get(int index) {
if (index < 0 || index >= size) {
throw new
IndexOutOfBoundsException();
} else {
return elements[index];
}
}
17
Kolla index:
Tillåt inte get(4) när size==2!
jonkv@ida
Listor 5: En listklass (forts.)

18
Effektiv representation – för de flesta operationer…
public void insert(int index, E element) {
if (size == elements.length) { … allocate more memory … }
}
System.arraycopy(elements, index, elements, index + 1, size - index);
elements[index] = element;
size++;
A B C D E F G H
list.add(2, "X");
A B C C D E F G H
Kopiera – tar tid!
A B X C D E F G H
Stoppa in
jonkv@ida
Listor 6: Stoppa in element

Vår listklass lagrar bara strängar!
public class StringList {
private String[] elements;
private int
size;
…
}
Behöver vi en listklass för varje elementtyp?
20
jonkv@ida
Elementtyper 1: Typspecifika listor?
21
public class ObjectList {
Array av Object-pekare,
private Object[] elements;
kan peka på objekt av godtycklig klass
private int size;
public ObjectList() {
this.elements = new Object[8];
this.size = 0;
}
public Object get(int index) {
if (index >= 0 && index <size) { return elements[index]; }
else /* Signal error */
}
public void add(Object element) {
if (size == elements.length) { /* Create a new array; copy old element */ }
elements[size] = element;
size++;
}
}
jonkv@ida
Elementtyper 2: Godtyckliga objekt

22
Nu får vi nya problem!
 1: Ingen typsäkerhet när vi adderar element!
▪ Vill ha en lista där vi stoppar in strängar:
ObjectList greetings = new ObjectList();
▪ Kan lägga in strängar:
greetings.add("hello");
▪ Kan råka lägga in cirklar också – inget fel vid kompilering eller körning!
greetings.add(new Circle(1, 1, 3));
public class ObjectList {
public ObjectList() { … }
public Object get(int index) { … }
public void add(Object element) { … }
}
jonkv@ida
Elementtyper 3: Problem
23
 Problem 2: Ingen typinformation när vi hämtar element!
ObjectList greetings = new ObjectList();
greetings.add("hello");
greetings.add(new Circle(1, 1, 3));
…
String str = greetings.get(0);
// Kompileringsfel
String str = (String) greetings.get(0);
// OK
Vi måste tala om för kompilatorn:
"Jag vet att jag la en sträng på position 0 – jag lovar!"
Krävs en cast – extra arbete för oss
public class ObjectList {
public ObjectList() { … }
public Object get(int index) { … }
public void add(Object element) { … }
}
jonkv@ida
Elementtyper 4: Problem
 Problem 3: Tänk om vi har fel!
ObjectList greetings = new ObjectList();
greetings.add("hello");
greetings.add(new Circle(1, 1, 3));
for (int i = 0; i < greetings.size(); i++) {
String str = (String) greetings.get(i);
// Runtime error for i=1 – it’s a Circle!
}
Upptäcks inte när programmet kompileras
24
jonkv@ida
Elementtyper 5: Problem
void printMult3() {
for (int i = 1; i <= 13; i++) {
System.out.println(3 * i);
}
}
void printMult5() {
for (int i = 1; i <= 13; i++) {
System.out.println(5 * i);
}
}
void printMult(int num) {
for (int i = 1; i <= 13; i++) {
System.out.println(num * i);
}
}
void printMult4() {
for (int i = 1; i <= 13; i++) {
System.out.println(4 * i);
}
}
26
num är en
heltalsvariabel
Kan ha värdet
3, 4, 5, 8, …
void printMult8() {
for (int i = 1; i <= 13; i++) {
System.out.println(8 * i);
}
}
jonkv@ida
Vanliga parametrar till metoder
class ListOfString {
String[] elements;
int
length;
{…}
String get(int index)
void add(String element) { … }
}
class MyList<E> {
E[]
elements;
int
length;
E
get(int index)
void add(E element)
}
class ListOfCircle {
Circle[] elements;
int
length;
{…}
Circle get(int index)
void add(Circle element) { … }
}
27
class ListOfShape {
Shape[] elements;
int
length;
{…}
Shape get(int index)
void add(Shape element) { … }
}
E är en
typvariabel
{…}
{…}
Kan ha värdet
String, Shape, …
class ListOfButton {
Button[] elements;
int
length;
{…}
Button get(int index)
void add(Button element) { … }
}
jonkv@ida
Typparametrar till klasser

28
Generiska typer med typparametrar
class MyList<E> {
E[]
elements;
int
length;
E
get(int index)
void add(E element)
}
En array där elementen har typ E
– verkliga typen är inte angiven än
{ return elements[index]; }
{ … } // Takes a parameter of type E
 Kan "instansieras" med olika typer som parameter
MyList<String> – nästan exakt som:
class MyList<String> {
String[] elements;
int
length;
{…}
String get(int index)
void add(String element) { … }
}
MyList<Shape> – nästan exakt som:
class MyList<Shape> {
Shape[] elements;
int
length;
{…}
Shape get(int index)
void add(Shape element) { … }
}
jonkv@ida
Generics 1: Intro
class MyList<E> {
E[] elements;
int length;
E get(int index)
void add(E element)
}
29
{ return elements[index]; }
{…}
 En lista där E=String:
MyList<String> greetings = new MyList<String>();
greetings.add("hello");
// OK
greetings.add(new Circle(1, 1, 3));
// Compile-time error: add(String)
String str = greetings.get(0);
// No cast needed: String get(int index)
 En lista där E=MyList<String>  en lista av listor!
MyList<MyList<String>> lists = new MyList<MyList<String>>();
lists.add(greetings);
jonkv@ida
Generics 2: Användningsexempel
class MyList<E> {
E[] elements;
int length;
E get(int index)
void add(E element)
}
{ return elements[index]; }
{…}
 Mycket repetition:
MyList<MyList<String>> listor = new MyList<MyList<String>>();
 Syntaktiskt socker: Diamant-operatorn (betyder "samma som förut")
MyList<MyList<String>> listor = new MyList<>();
DRY-principen: Don’t RepeatYourself!
Regelbrott är WET: Write Everything Twice…
30
jonkv@ida
Generics 3: Att skriva mindre
class MyList<E> {
E[] elements;
int length;
E get(int index)
void add(E element)
}
{ return elements[index]; }
{…}
 Man kan använda en generisk typ utan att ange typparametrar:
MyList listor = new MyList(); // Defaultvärde för E blir Object
 Enbart för kompatibilitet med gammal kod!
▪ Generics kom redan 2004
▪ Gammal kod borde fortfarande gå genom kompilatorn, men med varningar
▪ Gör inte detta i ny kod!
31
jonkv@ida
Generics 4: "Råa" typer

Kallas generisk programmering, ger oss parametrisk polymorfism
 Samma namn (MyList)
 Olika beteende (beroende på typparameter)

Jämför med subtypspolymorfism
 Samma metodnamn, flera implementationer inom en typhierarki
 Olika implementation väljs dynamiskt, beroende på verklig objekttyp

32
Jämför med ad-hoc-polymorfism (overloading)
 Samma metodnamn, flera implementationer i samma klass
 Olika implementation väljs statiskt, beroende på statiska parametertyper
jonkv@ida
Parametrisk polymorfism
En typparameter
måste ange en objekttyp!
class List<E> {
E[]
elements;
int
length;
E
get(int index)
void add(E element)
}
{…}
{…}
List<String> strings; // OK
List<Button> buttons; // OK
List<int> numbers; // Does not work!
34
…för egentligen
skapas bara en klass!
class List {
Object[] elements;
int
length;
{…}
Object get(int index)
void
add(Object element) { … }
}
Kompilatorn
tar hand om resten
Sparar minne…
men int är inget Object!
jonkv@ida
Typparametrar och objekttyper

35
Hur skapar vi en listklass som accepterar heltal?
Implementera om strukturerna?
class IntArrayList {
private int[] elements;
private int length;
public int get(int index) {
return elements[index];
}
void add(int element) { … }
}
Repetera för 8 primitiva typer
och för varje datastruktur
Kan göras – finns färdiga bibliotek
på nätet (GNU Trove, …)
Använd wrappers!
public class Integer {
private final int value;
public Integer(int value) {
this.value = value;
}
public int intValue() {
return value;
}
}
Repetera för 8 primitiva typer
 klart
jonkv@ida
Wrappers 1: Intro

Det finns en wrapper-klass för varje primitiv datatyp
36
jonkv@ida
Wrappers 2: Wrapper-objekt

37
För att skapa wrapper-objekt:
 Kan använda vanlig konstruktor
Number ten = new Integer(10);
Number pi = new Double(3.14);
 Bättre: Använd statiska fabriksmetoden valueOf()
Number ten = Integer.valueOf(10);
Number pi = Double.valueOf(3.14);
Sparar tid och minne: Återanvänder objekt för vanliga värden!
public class Integer {
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
Fungerar för att wrappers är immutable:
}
Värden kan inte ändras
}
jonkv@ida
Wrappers 3: Skapa

Resulterar i objekt  kan lagras i listor, objektpekare, …
List<Number> numbers = new ArrayList<>();
numbers.add(Integer.valueOf(10));
numbers.add(Double.valueOf(3.14));
Det är BARA då vi behöver wrappers!
Använd int, double, … i normalfallet!

För att hämta ut värdet: Anropa typeValue()
Number intobj
int val0
= numbers.get(0);
= intobj.intValue();
double val1
= numbers.get(1).doubleValue();
38
jonkv@ida
Wrappers 4: Användning

Kan använda automatisk boxing och unboxing
 ("Paketinslagning")
List<Number> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(3.14);
double val1 = numbers.get(1);

VARNING: Osynlig ineffektivitet!
 Kan skapa nya objekt
 Tar (lite) extra tid att plocka ut värden ur objekt
 Vissa rekommenderar explicit boxing / unboxing istället
39
jonkv@ida
Wrappers 5: Användning
int[] numbers = new int[]
{ 12, 14 ,16, 18, 20 }
List<Integer> list = new ArrayList<>();
list.add(12); list.add(14); list.add(16); list.add(18); list.add(20);
Array
Object
header:
length
[0]
[1]
[4]
(data)
5
12
14
20
Wrappers ger mindre
andel overhead om
strukturerna är mer
komplexa…
40
jonkv@ida
Wrappers 6: Använder mer minne
ArrayList
Object
header:
size
arr
Object
header:
length
[0]
[1]
[4]
5
Object
header:
value
(data)
Object
header:
value
(data)
(data)
12
(data)
14
5
Object
header:
value
(data)
20

Python har inga primitiva typer, bara objekttyper
 Trevligare på ytan – slipper bry sig om skillnaden
 Vanliga heltal har metoder!
▪ >>> x = 10
▪ >>> x.bit_length()
4
▪ >>> x.__add__(10)
20
 I Java: Kan välja mellan
▪ Primitiva typer – inte objekt, vissa begränsningar
▪ Wrapperklasser – är objekt, men långsammare, kräver mer minne
41
jonkv@ida
Wrappers 7: Python?
Java Collections Framework
[email protected] – 2016

43
Collections Framework: Många sammansatta datastrukturer
 1) Uppsättning gränssnitt för listor, köer, mängder, mappningar
 De viktigaste:
Kom ihåg: Gränssnitt ger oss frihet att välja implementation!
jonkv@ida
Collections Framework 1: Intro
 2) En uppsättning implementationer
44
jonkv@ida
Collections Framework 2: Intro
 3) Några hjälpklasser
45
jonkv@ida
Collections Framework 3: Intro

Collection<E>: Generell samling av objekt
 Vissa samlingar är ordnade
▪ Listor har ett första element –
inte mängder
 Vissa tillåter dubblerade element
▪ Listor kan innehålla två identiska element –
inte mängder
47
jonkv@ida
Collection 1: Intro
48
 Lägga till element:
▪ c.add(E)
▪ c.addAll(Collection)
 Testa innehåll:
▪ c.isEmpty(), c.size()
▪ c.contains(Object obj)
▪ c1.containsAll(Collection c2)
– Alla element i c2 finns i c1?
 Hämta alla element:
▪ c.toArray()
– En Object[ ] som innehåller samma element
 Ta bort element:
▪ c.clear()
▪ c.remove(Object)
– Tar bort alla element
jonkv@ida
Collection 2: Grundläggande funktionalitet

49
List<E> extends Collection<E>
 Alltid ordnad: Element har index
 Implementeras av
▪ ArrayList
– Mycket vanlig, implementation liknar våra tidigare exempel
▪ LinkedList
– Ganska vanlig, andra egenskaper
▪ Stack, Vector
– Använd inte, deprecated
jonkv@ida
List 1: Intro

50
Principen bakom länkade listor:
LinkedList
Object
header:
size
first
(data)
5
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
12
En extra listnod per element
 använder mer minne
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
14
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
16
jonkv@ida
Länkade listor (1)
ListNode
Object
header:
next
prev
value
Snabbt att skjuta in / ta bort värden
LinkedList
Object
header:
size
first
(data)
5
ListNode
Object
header:
next
prev
value
Object
header:
value
Object
header:
value
(data)
(data)
12
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
14
51
(data)
(data)
15
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
16
jonkv@ida
Länkade listor (2)
52
Tar lång tid att ta fram värde nummer n i listan
LinkedList
Object
header:
size
first
(data)
5
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
12
ListNode<E> get(int index) {
ListNode<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
}
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
14
ListNode
Object
header:
next
prev
value
Object
header:
value
(data)
(data)
16
jonkv@ida
Länkade listor (3)
53
 Hämta / hitta element
▪ list.get(index)
▪ list.indexOf(Object needle), list.lastIndexOf(Object needle)
▪ Collections can hitta dellistor, göra binärsökning, hitta min/max-element
 Lägga till och ta bort
▪ list.add(E value)
– ärvs från Collection!
▪ list.add(int index, E value) – flyttar element efter givet index
▪ list.addAll(int index, Collection c)
▪ list.remove(int index)
 Ändra element
▪ list.set(int index, E value)
▪ Collections kan söka/ersätta, fylla med ett värde, kopiera listor
 Omarrangera listor
▪ Collections kan blanda, sortera, rotera, reversera listor
jonkv@ida
List 2: Metoder
54
Arrayer används:
 För att implementera datatyper
 ArrayList måste använda en
“primitiv” array
 När varje nanosekund spelar roll
 Bara efter CPU-profilering som visar
att listhantering spelar roll
Listor används:
 Nästan alltid!
 Många hjälpfunktioner tillgängliga
 Kan lätt lägga till och ta bort
element, osv
 Används av många klasser i Javas
klassbibliotek
 …
 När varje byte spelar roll
 Bara efter minnesprofilering…
 Ibland om storleken är fixerad
 Om storleken varierar:
Låt listorna hantera detta!
Tetrislabben använder arrayer
eftersom Board-storleken
är fixerad!
jonkv@ida
List 3: Listor vs. arrayer

55
Queue<E> extends Collection<E>
 Kan lägga till i slutet av kön
 Kan ta bort i början av kön
 Implementeras av
▪ ArrayDeque, LinkedList
– grundläggande köstrukturer
 Varianter
▪ Deque: Även "på andra sidan" (Double-Ended QUEue)
▪ PriorityQueue
– har element i sorterad ordning
Vad händer om det är omöjligt?
Operation
Stoppa in element
Ta bort element
Se på första elementet
Signalerar fel – exception
add(e)
remove()
element()
Returnerar speciellt värde
offer(e)
poll()
peek()
jonkv@ida
Queue 1: Köer

56
Map<K,V> är Javas motsvarighet till dictionaries
 Associerar nycklar/keys K med värden V
 Vanlig klass, inte "språkfiness"  mer att skriva
>>> dict = {'a': 45, 'b': 39, 'c': 19}
>>> dict['a']
45
>>> dict['d'] = 4711
>>> dict
{'a': 45, 'c': 19, 'b': 39, 'd': 4711}
>>> len(dict)
4
▪ TreeMap
▪ HashMap
public static void main(String[] args) {
Map<Character,Integer> dict = new HashMap<>();
dict.put('a', 45);
dict.put('b', 39);
dict.put('c', 19);
System.out.println(dict.get('a'));
// 45
dict.put('d', 4711);
System.out.println(dict);
// {a=45, b=39, c=19, d=4711}
System.out.println(dict.size());
// 4
}
– sorterar elementen, måste ange sorteringsordning
– kräver hashkoder, förklaras i TDDD86
jonkv@ida
Map: Mappningar

Hur kan man iterera över alla element i en samling?
 Med en array eller ArrayList fungerar index utmärkt:
static boolean contains(List<?> haystack, Object needle) {
for (int i = 0; i < haystack.size(); i++) {
if (haystack.get(i).equals(needle)) return true;
}
return false;
}
58
jonkv@ida
Iteration 1: Med index

59
Hur kan man iterera över alla element i en samling?
 Med en LinkedList fungerar index, men långsamt:
static boolean contains(List<?> haystack, Object needle) {
for (int i = 0; i < haystack.size(); i++) {
if (haystack.get(i).equals(needle)) return true;
}
return false;
}
Node<E> get(int index) {
Node<E> x = first;
for (int j = 0; j < index; j++)
x = x.next;
return x;
}
get(0):
get(1):
get(2):
get(3):
get(4):
…
Gå genom element j=0
Gå genom element j=0, 1
Gå genom element j=0, 1, 2
Gå genom element j=0, 1, 2, 3
Gå genom element j=0, 1, 2, 3, 4
jonkv@ida
Iteration 2: Med index

Hur kan man iterera över alla element i en samling?
 Med en generell Collection (eller Set) finns inga index!
static boolean contains(Collection<?> haystack, Object needle) {
for (int i = 0; i < haystack.size(); i++) {
if (haystack.get(i).equals(needle)) return true;
}
return false;
}
Vi är egentligen inte intresserade av index!
Vi vill veta:
Finns det fler element?
Vad är nästa element?
60
jonkv@ida
Iteration 3: Utan index

61
Lösning: Gränssnittet Iterator
public interface Iterator<E> {
public boolean hasNext();
public E next();
…
}
Finns det fler element?
Vad är nästa element?
static boolean contains(Iterator<?> haystack, Object needle) {
while (haystack.hasNext()) {
Specialsyntax:
Object element = haystack.next();
Iterator för vilken elementtyp som helst
if (element.equals(needle))
return true;
Vet inte vilken elementtyp… men:
}
Det är i alla fall någon sorts Object!
return false;
}
Har en egen implementation för varje datastruktur,
eget sätt att hålla reda på "var vi är just nu"
jonkv@ida
Iteration 4: Iterator

62
Gränssnittet Iterable säger att objektet kan ge oss en iterator
public interface Iterable<E> {
public Iterator<E> iterator();
}

Implementeras av Collections och arrayer, kan användas i for
static boolean contains(Collection<?> haystack, Object needle) {
for (Object element : haystack) {
Loopen anropar haystack.iterator()
if (element.equals(needle)) return true;
}
Anta haystack är LinkedList
return false;

}
LinkedList.iterator() returnerar new
LinkedListIterator(), som vet hur man
int sum(int[] numbers)
effektivt itererar över länkade listor
for (int i : numbers) { … }
}
void printAll(List<String> greetings) {
for (String str : greetings) { … }
}
jonkv@ida
Iteration 5: Iterable och for(each)-loopar

Om man ändrar en samling medan man itererar över den:
 ConcurrentModificationException
 Har inget att göra med multitrådning!
static boolean contains(Iterable<?> haystack, Object needle) {
for (Object element : haystack) {
if (element.equals(needle)) return true;
if (…) {
ändra i haystack …
}
}
return false;
}
jonkv@ida
Iteration 6: ConcurrentModificationException 63

Iterator har en tredje metod
package java.util;
public interface Iterator<E> {
public boolean hasNext();
public E next();
public void remove();
}
Ta bort elementet
som just returnerades av next()
static void removeAllCopies(Iterable<String> haystack, Object needle) {
Iterator<String> iter = haystack.iterator();
while (haystack.hasNext()) {
String element = haystack.next();
if (element.equals(needle)) {
iter.remove();
}
}
}
Tas bort via iteratorn  ingen ConcurrentModificationException
64
jonkv@ida
Iteration 7: Ta bort element

65
jonkv@ida
"Fortsättning" i nästa kurs
Mer om datastrukturer:
 TDDD86 Datastrukturer, algoritmer och programmeringsparadigm,
http://kdb5.liu.se/liu/lith/studiehandboken/svkursplan.lasso?&k_budget_year=2016&k_ku
rskod=TDDD86