4 Listor

Listor
16
4
Listor
Tema: Listor, listimplementeringar - enkellänkad lista, sorterad lista, interfacet Comparable.
Litteratur: Avsnitt 2.1–2.3, 2.5–2.7, 2.9-2.10 (avsnitt 4.1–4.5, 4.8 i gamla upplagan). Läs också bilderna från föreläsning 3.
Använda ArrayList och LinkedList – skugga equals
U 28. I kursen arbetar vi bland annat med klasser och interface från Java Collections Framework.
Ett exempel på sådana är interfacet List samt klasserna ArrayList och LinkedList i paketet java.util. I klasserna ArrayList och LinkedList finns metoder för att hitta ett
element i listan, contains(Object), indexOf(Object) och remove(Object). Hur avgörs
om två element är ”lika”? Vem bestämmer vad som menas med ”lika” (den som implementerat listklassen eller den som använder klassen) och hur gör man det?
U 29. Antag att vi ska lagra böcker i en lista av någon av dessa typer. En bok beskrivs av följande
klass:
public class Book
private String
private String
private String
{
isbn;
title;
author;
public Book(String isbn, String title, String author) {
this.isbn = isbn;
this.title = title;
this.author = author;
}
public String toString() {
return author + ": " + title;
}
}
En bok identifieras av sitt ISBN-nummer. Gör de förändringar i klassen Book som behövs
för att metoderna contains, indexOf och remove ska fungera som förväntat.
U 30. Antag att vi har deklarerat följande lista och lagt in ett antal böcker av typen Book i listan:
List<Book> list = new ArrayList<Book>()
// satser för att lägga in böcker i listan
Lägg till sats/er för att ta reda på om boken med ISBN-nummer ”9780345917430” finns i
listan.
Enkellänkad lista
I några av uppgifterna används klasserna SingleLinkedList och ListNode:
public class SingleLinkedList<E>
private ListNode<E> first;
/** Creates an empty list. */
public SingleLinkedList() {
first = null;
}
{
Listor
17
/** Inserts the specified element at the beginning of this list. */
public void addFirst(E e) {
ListNode<E> n = new ListNode<E>(e);
n.next = first;
first = n;
}
...
/* Nested class. Represents a node which contains an element of type E. */
private static class ListNode<E> {
private E element;
private ListNode<E> next;
/* Creates a listnode which contains e. */
private ListNode(E e) {
element = e;
next = null;
}
}
}
U 31. Skriv programrader som skapar ett lista av typen SingleLinkedList för att lagra heltal
samt ser till att listan innehåller talen 1, 2, 3.
U 32.
a) Lägg till följande metod i klassen SingleLinkedList:
/** Returns the first element in this list.
Throws NoSuchElementException if this list is empty. */
E getFirst();
b) Lägg till följande metod i klassen SingleLinkedList:
/** Returns the last element from this list.
Throws NoSuchElementException if this list is empty. */
E getLast();
U 33. Lägg till följande metod i klassen SingleLinkedList:
/** Returns true if this collection contains the specified element. */
public boolean contains(Object x);
U 34. Lägg till följande metod i klassen SingleLinkedList:
/** Removes the first occurrence of the
if it is present. If this list does
Returns true if this list contained
if this list changed as a result of
boolean remove(Object e);
specified element from this list,
not contain the element, it is unchanged.
the specified element (or equivalently,
the call). */
Ledning:
• Utgå från din lösning på uppgift U 33.
• Tänk på att du för att kunna ta bort ett element måste ha en referens till föregående
element i listan. Håll därför reda både på aktuellt element och dess föregångare när
du går framåt i listan under sökningen.
• Tänk på specialfallen (tom lista, det är första elementet som ska tas bort ...).
Listor
18
Implementering genom delegation
U 35. I läroboken, kapitel 2, finns en implementering av en klass OrderedList som representerar
en följd av element, sorterad i växande ordning. Klassen har följande utformning:
public class OrderedList<E extends Comparable<E>> implements Iterable<E> {
private LinkedList<E> theList;
public OrderedList() {
theList = new LinkedList<E>();
}
public void add(E obj) {
ListIterator<E> itr = theList.listIterator();
while (itr.hasNext()) {
if (obj.compareTo(itr.next()) < 0) {
itr.previous();
itr.add(obj);
return;
}
}
itr.add(obj);
}
public E get(int index) {
return theList.get(index);
}
public Iterator<E> iterator() {
return theList.iterator();
}
public int size() {
return theList.size();
}
}
I metoden add ser man till att listan blir sorterad i storleksordning genom att leta upp
rätt position för objektet obj. Övriga metoder utför sin uppgift genom att ”delegera” till
motsvarande operation i klassen LinkedList (som visas i koden ovan för metoderna get,
iterator och size).
Varför implementerar man inte OrderedList genom att ärva från klassen LindkedList<E>
enligt följande mönster?
public class OrderedList<E extends Comparable<E>> extends LinkedList<E>
U 36. Lägg till metoden remove i klassen OrderedList. Tänk på utnyttja att listan är sorterad så
att du inte undersöker onödigt många element.
/** Removes the first occurrence of the
if it is present. If this list does
Returns true if this list contained
if this list changed as a result of
boolean remove(E obj);
specified element from this list,
not contain the element, it is unchanged.
the specified element (or equivalently,
the call). */
Listor
19
U 37. I OrderedList finns det en metod iterator som returnerar en Iterator för listan. Varför
finns det inte också en metod listIterator som returnerar en ListIterator?
Implementera interfacet Comparable
U 38. I klassen OrderedList i uppgift U 35 anges typparametern på följande sätt:
<E extends Comparable<E>>
Vad innebär det? Skulle man istället kunna skriva bara <E>?
U 39. Antag att vi ska använda klassen OrderedList i uppgift U 35 för att hålla reda på patienter
som väntar på en akutmottagning. Varje patient tilldelas en prioritet, som är ett heltal. Ett
lågt värde på detta attribut motsvarar hög prioritet. Patienter representeras av följande
klass:
public class Patient {
private String firstname;
private String lastname;
private int prio;
public Patient(String firstname, String lastname, int prio) {
this.firstname = firstname;
this.lastname = lastname;
this.prio = prio;
}
...
}
Se till att klassen implementerar gränssnittet Comparable<T>. Det är prioriteterna som ska
jämföras här och inte namnen. Tänk också på att det är en god regel att också omdefiniera
metoden boolean equals(Object x) som finns i superklassen Object så att dessa båda
metoder är ense om när två objekt av klassen är lika.
U 40. Hur ska metoden compareTo implementeras om man istället för prioritet ska jämföra
namnen? Antag att man i första hand ska sortera efter efternamn.