Zoo
ImplementationZoo
as Linked Listadd(Animal a)
to append a new Animal
contains(Animal a)
to check if an Animal
is in the Zoo
feedAnimals()
to feed the Animals
We discussed remove(Animal a)
to remove an Animal
remove()
in Picturesremove()
in Code public void remove (Animal a) {
Node curr = head;
if (curr == null) {
return;
}
if (curr.getAnimal().equals(a)) {
head = curr.getNext();
return;
}
Node prev = curr;
curr = curr.getNext();
while (curr != null) {
if (curr.getAnimal().equals(a)) {
prev.setNext(curr.getNext());
return;
}
prev = curr;
curr = curr.getNext();
}
}
With the array Animal[] zoo
we could access all of the Animal
s easily:
Animal[] zoo;
...
for (int i = 0; i < zoo.length; i++) {
// do something with zoo[i]
}
How could we do something similar with the Zoo
class?
Zoo
next()
that:
null
)
null
, return null
hasNext()
to check if there is a next animal(We will see a more elegant way using iterators later…)
The logic and structure of our Zoo
is great!
But what if we want to store things other than Animal
s?
How could we represent a list of anything?
Object
public class ListOfObjects {
private Node head = null;
private Node tail = null;
public void add (Object obj) {
...
}
public void remove (Object obj) {
...
}
public boolean contains (Object obj) {
...
}
public Object next () {
...
}
}
class Node {
private Object obj;
private Node next;
public Node (Object obj) {
this.obj = obj;
next = null;
}
public void setNext (Node nd) {
next = nd;
}
public Node getNext () {
return next;
}
public Object getObj () {
return obj;
}
}
ListOfObjects list = new ListOfObjects();
list.add(new Elephant("Alice"));
...
ListOfObjects list = new ListOfObjects();
list.add(new Elephant("Alice"));
...
Casting! Every time we access something in the list, it must be cast as the correct type:
Animal a = (Animal) list.next()
This is annoying…
ListOfObjects list = new ListOfObjects();
list.add(new Elephant("Alice"));
...
There is nothing requiring us to use the same datatype
list.add(new Platypus("Bob"));
list.add("Adding a String now");
list.add(Integer.getInteger("3745"));
These operations are perfectly valid!
Idea: Write a GenericList
class that
Declare class
with a type, T
:
public class GenericList<T> {
...
}
Inside the class, T
can be used like a variable representing the type:
// add an item of type T
public void add (T item) {
...
}
// get next item of type T
public T next () {
...
}
Node
Node
generic:
class Node<T> {
private T item;
private Node<T> next;
...
}
Node
an inner class:
public class GenericList<T> {
...
class Node {
private T item;
private Node<T> next;
...
}
}
// make lists storing different types
GenericList<Animal> zoo = new GenericList<Animal>();
GenericList<Person> amherst = new GenericList<Person>();
// populate the lists
zoo.add(new Platypus("Alice"));
amherst.add(new Person("Bob"));
...
// these give errors!
amherst.add(new Elephant("Eve"));
zoo.contains("Bob");