Made our linked list generic:
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 () {
...
}
Now we can use the same GenericList
to store any type of object:
GenericList<Animal> zoo = new GenericList<Animal>();
GenericList<Person> school = new GenericList<Person>();
GenericList<Integer> numbers = new GenericList<Integer>();
...
We also implemented methods for iteration:
hasNext()
returns true
if there is another element in the listnext()
returns the next element in the listTo access all the elements in the list:
while (zoo.hasNext()) {
Animal a = zoo.next();
...
}
public void add (T item) {
Node nd = new Node(item);
if (tail != null) {
tail.setNext(nd);
tail = nd;
} else {
head = nd;
tail = nd;
iter = nd;
}
}
When we call list.add(item)
, the item
is added to the end of the list
Consider
GenericList<Integer> list = new GenericList<Integer>();
list.add(4);
list.add(2);
list.add(3);
while (list.hasNext()) {
System.out.println(list.next());
}
What does it print?
Suppose we wanted to store/print elements in sorted order:
SomeList<Integer> list = new SomeList<Integer>();
list.insert(4);
list.insert(2);
list.insert(3);
while (list.hasNext()) {
System.out.println(list.next());
}
We want to see output:
2
3
4
How might we accomplish this?
Use procedure similar to remove
method:
prev
and curr
nodescurr
value is at least 5
prev
value is smaller than 5
5
between prev
and curr
Special cases:
head
tail
public void insert (T item) {
Node nd = new Node(item);
// check if empty
if (tail == null) {
head = nd; tail = nd; iter = nd;
return;
}
// check if insert at head
if (item <= head.item) {
nd.next = head; head = nd; iter = nd;
return;
}
Node prev = head;
Node curr = prev.next;
// find location to insert item: prev.item < item <= curr.item
while (curr != null && item > curr.item) {
prev = curr;
curr = curr.next;
}
// check if tail insert
if (curr == null) {
prev.next = nd; tail = nd;
return;
}
prev.next = nd;
nd.next = curr;
}
public void insert (T item) {
Node nd = new Node(item);
if (tail == null) {
head = nd; tail = nd; iter = nd;
return;
}
if (item <= head.item) {
nd.next = head; head = nd; iter = nd;
return;
}
Node prev = head;
Node curr = prev.next;
while (curr != null && item > curr.item) {
prev = curr;
curr = curr.next;
}
if (curr == null) {
prev.next = nd; tail = nd;
return;
}
prev.next = nd;
nd.next = curr;
}
In order to store a sorted collection, must be able to compare pairs of elements.
String
s alphabeticallyAnimal
s by…
It doesn’t make sense to compare everything!
Goals:
class
supports comparisonSortedList
A way of specifying what a class can/must do
Comparable
InterfaceJava defines the Comparable<T>
interface:
For a class
to be Comparable
it must have a method
public int compareTo(T o)
If a
and b
are Comparable
objects:
a.compareTo(b)
is less than 0
, then a
is “smaller than” b
a.compareTo(b)
is greater than 0
, then a
is “larger than” b
a.compareTo(b)
is 0
then they are treated as equalComparable
Integer
, Double
, …
String
Animal
s ComparableTo implement an interface, must:
public class Animal implements Comparable<Animal> {
...
}
public class Animal implements Comparable<Animal> {
...
public int compareTo(Animal a) { ... }
}
How should we compare two Animal
s?
Create a new class SortedList
GenericList
Comparable
A new declaration:
// T a generic type, but must implement the Comparable<T>
// interface
public class SortedList<T extends Comparable<T>> {
...
}
SortedList
An interface
is a contract:
interface
, you must provide certain functionalitySorting example:
Comparable
class
determines what is meant by comparisonSeparate interface from implementation