1 / 61100%
6/11/09
Collections and Linked Lists
This week the focus is on
the concept of a collection
the importance of separating the interface from
the implementation
generic types and their use in collection classes
the difference between fixed and dynamic
implementations
dynamically linked lists
the Java Collections API
6/11/09
Outline
Introduction to Collections
A Bag Collection
Array Implementation of a Bag
Linked Lists
Linked Implementation of a Bag
6/11/09
Introduction to Collections
We are used to collections of items:
stamps, CDs, keys, etc.
A collection is an object that serves as a
repository for other objects
A collection provides services to add,
remove, and manage the elements it
contains
The underlying data structure used to
implement the collection is independent of
the operations provided
6/11/09
Introduction to Collections
Collections can be separated into two
categories
linear: elements are organized in a straight line
nonlinear: elements are organized in
something other than a straight line
Organization elements, relative to each
other, is usually determined by
the order in which they were added to the
collection
some inherent relationship among the
elements
6/11/09
Separating Interface from
Implementation
An abstract data type (ADT) is a set of data
and the particular operations that are
allowed on that data
An ADT is considered abstract because the
operations you can perform on it are
separated from the underlying
implementation
A collection
is an abstract data type
defines interface operations through which the
user can manage the objects in the collection,
6/11/09
Separating Interface from
Implementation
The details of how a collection is
implemented to fulfill that definition
should be an independent issue
For every collection we examine, we
should consider
How does the collection operate, conceptually?
What operations are included in the interface
to the collection?
What kinds of problems does the collection
help us solve?
How might the collection be implemented?
6/11/09
Separating Interface from
Implementation
Class that uses
the collection
Class that
implements
the collection
Interface to
collection
Services provided by collection
that adhere to an interface
6/11/09
Generic Types
Java permits us to define a class based on
a generic type
Our defined class will then be able to
operate on, store, and manage objects
whose type is not specified until the class
is instantiated
Example: we can define a Group class that
stores and manages a group of objects.
Using polymorphism, we can define Group
to store references to the Object class
6/11/09
Generic Types
However, any type of object could then be
stored in our Group, resulting in a loss of
control
A better approach is to define the Group to
store a generic type T (a convention,
though we can use any letter)
class group<T>
{
// declarations and code that manages objects of type T
}
6/11/09
Generic Types
Instantiating a Group of Product objects
Group<Product> group1 = new Group<Product>;
Instantiating a Group of Friend objects
Group<Friend> group2 = new Group<Friend>;
A generic type T can not be instantiated
Sometimes we want our stored items to be
Comparable
class Group<T extends Comparable<T>>
{
}
6/11/09
Outline
Introduction to Collections
A Bag Collection
Array Implementation of a Bag
Linked Lists
Linked Implementation of a Bag
A Bag Collection
A bag is a collection that
facilitates the selection of
random elements from the
group
A bag is nonlinear; elements
in the bag have no particular
positional relationship to
each other
The implementation of the
bag will store the elements
in an array or some other
6/11/09
javafoundations.Bag
Interface
//*******************************************************************
// Bag.java Java Foundations
//
// Defines the interface to a bag collection.
//*******************************************************************
package javafoundations;
public interface Bag<T> extends Iterable<T>
{
// Adds the specified element to the bag.
public void add (T element);
// Removes and returns a random element from the bag.
public T remove();
// Returns true if the bag contains no elements and false
// otherwise.
public boolean isEmpty();
// Returns the number of elements in the bag.
public int size();
// Returns a string representation of the bag.
public String toString();
}
6/11/09
A Bag Collection
Notice that the interface is defined to
operation on type T objects
the add method will add elements of type T
the remove method will return elements of type
T
The other methods support basic
operations on the collection
Bag extends the Iterable interface, which
provides one method that returns an
Iterator object
Bingo Game
A bag collection is
perfectly suited to
support a Bingo
game
The collection will
hold BingoBall
objects and will use
an array as the basis
of the
implementation
Our collection will be
known as an
B I N G O
9 25 34 48 69
15 19 31 59 74
2 28 FREE 52 62
7 16 41 58 70
12 20 38 47 64
6/11/09
Bingo.java
//********************************************************************
// Bingo.java Java Foundations
//
// Demonstrates the use of a bag collection.
//********************************************************************
import javafoundations.ArrayBag;
public class Bingo
{
//-----------------------------------------------------------------
// Creates all 75 Bingo balls and stores them in a bag. Then
// pulls several balls from the bag at random and prints them.
//-----------------------------------------------------------------
public static void main (String[] args)
{
final int NUM_BALLS = 75, NUM_PULLS = 20;
ArrayBag<BingoBall> bingoBag = new ArrayBag<BingoBall>();
BingoBall ball;
for (int num = 1; num <= NUM_BALLS; num++)
bingoBag.add (new BingoBall(num));
(more…)
6/11/09
Bingo.java
System.out.println ("Size: " + bingoBag.size() + "\n");
for (int num = 1; num <= NUM_PULLS; num++)
{
ball = bingoBag.remove();
System.out.println (ball);
}
}
}
6/11/09
BingoBall.java
//********************************************************************
// BingoBall.java Java Foundations
//
// Represents a ball used in a Bingo game.
//********************************************************************
public class BingoBall
{
private char letter;
private int number;
//-----------------------------------------------------------------
// Sets up this Bingo ball with the specified number and the
// appropriate letter.
//-----------------------------------------------------------------
public BingoBall (int num)
{
number = num;
if (num <= 15)
letter = 'B';
else
(more…)
6/11/09
BingoBall.java
if (num <= 30)
letter = 'I';
else
if (num <= 45)
letter = 'N';
else
if (num <= 60)
letter = 'G';
else
letter = 'O';
}
//-----------------------------------------------------------------
// Returns a string representation of this Bingo ball.
//-----------------------------------------------------------------
public String toString ()
{
return (letter + " " + number);
}
}
6/11/09
Outline
Introduction to Collections
A Bag Collection
Array Implementation of a Bag
Linked Lists
Linked Implementation of a Bag
6/11/09
An Array Implementation of
a Bag
An array can be used to store the
elements of our collection
However, an array has a fixed size once it
is created
Collections sometimes are limited to a
specific size
We don’t wish to have our bag limited by
this constraint
When the bag is “full” we want to support
reallocating space for the array to “grow”
6/11/09
javafoundations.ArrayBag
Class
//********************************************************************
// ArrayBag.java Java Foundations
//
// Represents an array implementation of bag collection.
//********************************************************************
package javafoundations;
import java.util.*;
import javafoundations.exceptions.EmptyCollectionException;
public class ArrayBag<T> implements Bag<T>
{
private final int DEFAULT_CAPACITY = 10;
private int count;
private T[] contents;
private static Random rand = new Random();
(more…)
6/11/09
javafoundations.ArrayBag
//-----------------------------------------------------------------
// Creates an empty bag using the default capacity.
//-----------------------------------------------------------------
public ArrayBag()
{
count = 0;
contents = (T[]) (new Object[DEFAULT_CAPACITY]);
}
//-----------------------------------------------------------------
// Adds the specified element to this bag by storing the element
// at the end of the list, expanding the array capacity if needed.
//-----------------------------------------------------------------
public void add (T element)
{
if (count == contents.length)
expandCapacity();
contents[count] = element;
count++;
}
(more…)
6/11/09
javafoundations.ArrayBag
//-----------------------------------------------------------------
// Removes a random element from this bag, shifting the last
// element into its place to keep the list contiguous. Throws
// EmptyCollectionException if this bag is empty.
//-----------------------------------------------------------------
public T remove() throws EmptyCollectionException
{
if (count == 0)
throw new EmptyCollectionException ("Remove operation " +
"failed. The bag is empty.");
int index = rand.nextInt(count);
T result = contents[index];
count--;
contents[index] = contents[count];
contents[count] = null;
return result;
}
(more…)
6/11/09
javafoundations.ArrayBag
//-----------------------------------------------------------------
// Returns true if this bag contains no elements, and false
// otherwise.
//-----------------------------------------------------------------
public boolean isEmpty()
{
return (count == 0);
}
//-----------------------------------------------------------------
// Returns the number of elements in this bag.
//-----------------------------------------------------------------
public int size()
{
return count;
}
(more…)
6/11/09
14.3 –
javafoundations.ArrayBag
//-----------------------------------------------------------------
// Returns an iterator for this bag.
//-----------------------------------------------------------------
public Iterator<T> iterator()
{
ArrayIterator<T> iter = new ArrayIterator<T>();
for (int index = 0; index < count; index++)
iter.add(contents[index]);
return iter;
}
//-----------------------------------------------------------------
// Returns a string representation of this bag.
//-----------------------------------------------------------------
public String toString()
{
String result = "Bag Contents:\n";
for (int index=0; index < count; index++)
result += contents[index] + "\n";
return result;
}
(more…)
6/11/09
14.3 –
javafoundations.ArrayBag
//-----------------------------------------------------------------
// Creates a new array to store the contents of this bag with
// twice the capacity of the old one.
//-----------------------------------------------------------------
private void expandCapacity()
{
T[] larger = (T []) (new Object[contents.length*2]);
int location = 0;
for (T element : contents)
larger[location++] = element;
contents = larger;
}
}
6/11/09
An Array Implementation of
a Bag
Our collection class (ArrayBag) is a member
of the javafoundations package
The elements in the collection are stored
in an array named contents and an integer
variable named count is used to
keep track of the number of elements currently
in the bag
identify the next open position in the array
where the next element would be inserted
6/11/09
An Array Implementation of
a Bag
We can not instantiate an array of generic
types, so we instantiate an array of Object
references and cast it
contents = (T[]) (new Object[DEFAULT_CAPACITY]);
The compiler warns us that this is an
unchecked cast, but this is just a warning
The add method
accepts an element of type T and stores it in
the array, but
must first check the capacity of the array and
expand the capacity if needed
6/11/09
An Array Implementation of
a Bag
The remove method returns a randomly
selected element from the array if at least
one element exists in the bag
If no elements exist, an
EmptyCollectionException is thrown and
returns control to the calling method
The value of count must be carefully and
consistently managed as it is important to
successfully managing the collection
6/11/09
Collection Iterators
It’s common to traverse the elements of a
collection, visiting” each one in turn
The user decides what processing occurs
when each element is visited
We use iterators in our collection to
perform various kinds of traversals
Our collection’s iterator method returns
an Iterator object that can traverse the
contents of the bag
6/11/09
javafoundations.ArrayIterato
r
//********************************************************************
// ArrayIterator.java Java Foundations
//
// Represents an iterator over the elements of a collection.
//********************************************************************
package javafoundations;
import java.util.*;
public class ArrayIterator<T> implements Iterator<T>
{
private int DEFAULT_CAPACITY = 10;
private int count; // the number of elements in the iterator
private int current; // the current position in the iteration
private T[] items; // the iterator's storage for elements
//-----------------------------------------------------------------
// Sets up this iterator.
//-----------------------------------------------------------------
public ArrayIterator()
{
items = (T[]) (new Object[DEFAULT_CAPACITY]);
count = 0;
current = 0;
}
(more…)
6/11/09
javafoundations.ArrayIterato
r
//-----------------------------------------------------------------
// Adds the specified item to this iterator.
//-----------------------------------------------------------------
public void add (T item)
{
if (count == items.length)
expandCapacity();
items[count] = item;
count++;
}
//-----------------------------------------------------------------
// Returns true if this iterator has at least one more element to
// deliver in the iteration.
//-----------------------------------------------------------------
public boolean hasNext()
{
return (current < count);
}
(more…)
6/11/09
javafoundations.ArrayIterato
//-----------------------------------------------------------------
// Returns the next element in the iteration. If there are no more
// elements in this iteration, a NoSuchElementException is thrown.
//-----------------------------------------------------------------
public T next()
{
if (! hasNext())
throw new NoSuchElementException();
current++;
return items[current - 1];
}
//-----------------------------------------------------------------
// The remove operation is not supported in this collection.
//-----------------------------------------------------------------
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
(more…)
6/11/09
javafoundations.ArrayIterato
r
//-----------------------------------------------------------------
// Exapands the capacity of the storage array
//-----------------------------------------------------------------
private void expandCapacity()
{
T[] larger = (T []) (new Object[items.length*2]);
int location = 0;
for (T element : items)
larger[location++] = element;
items = larger;
}
}
6/11/09
javafoundations.ArrayIterato
Since the ArrayIterator implements the
Iterator interface, we must include the
hasNext, next, and remove methods
The class is so named because it uses an
array as the underlying structure to hold
the elements in the iterator
It’s generally not a good idea to remove an
element from a collection using an iterator
Another advantage to of making a
collection Iterable is that then it can be
processed using the for-each loop
6/11/09
Outline
Introduction to Collections
A Bag Collection
Array Implementation of a Bag
Linked Lists
Linked Implementation of a Bag
6/11/09
Linked Lists
An array is one way we can implement a
linear collection
Arrays however are limited in one sense
because they have a fixed size
Resizing as needed must be done carefully
and is not an efficient implementation
A linked structure is a data structure that
uses object reference variables to create
links between objects
Linked structures are the primary
alternative to an array-based
6/11/09
Linked Lists
A class can define as instance data an
object reference to another object of the
same class
Example: suppose we have a class named
Person as follows
public class Person
{
private String name;
private String address;
private Person next; // a link to another Person
object
6/11/09
Linked Lists
Using only this one class, a linked
structure can be created
One Person object contains a link to another
Person object
This second object contains a reference to a
third Person, etc.
This type of object is sometimes called
self-referential
This kind of relationship forms the basis of
a linked list
a linked structure in which one object refers to
6/11/09
Linked Lists
front
6/11/09
Linked Lists
A simple linked list is only one kind of
linked structure
In a doubly linked list, each node in the list
stores both a reference to the next
element and a reference to the previous
one
front rear
6/11/09
Linked Lists
Linked lists
has no upper bound on its capacity other than
the limitations of memory in the computer
is considered to be a dynamic structure because
its size grows and shrinks as needed to
accommodate the number of elements stored
6/11/09
Managing Linked Lists
There are a few basic techniques involved
in managing nodes on the list, no matter
what the list is used to store
Special care must be taken when dealing
with the first node in the list so that the
reference to the entire list is maintained
appropriately
A node may be inserted at any location
at the front of the list,
among the interior nodes, or
at the end of the list
6/11/09
Inserting a node at the
front
front
nod
e
2
1
6/11/09
Inserting a node in the
middle
front
nod
e
current
1
2
6/11/09
Deleting the first node in
the list
front
3
2
nod
e
1
6/11/09
Deleting an interior node
front
2
current
1
previous
6/11/09
Elements Without Links
We still need to examine one key aspect of
linked lists
We need to separate the details of the
linked list structure from the elements that
the list stores
The flaw in our earlier logic (see Person
class) is that the self-referential Person
class must be designed so that it “knows”
it may become a node in a linked list
This violates the goal of separating the
implementation details from the parts of
6/11/09
Elements Without Links
Solution: define a separate node class that
serves to link the elements together
Node class is simple, it contains two
references
one to the next node, and
one to the element that is being stored
The linked list nodes can still be managed
as discussed previously
6/11/09
Elements Without Links
front
6/11/09
Outline
Introduction to Collections
A Bag Collection
Array Implementation of a Bag
Linked Lists
Linked Implementation of a Bag
6/11/09
A Linked Implementation of
a Bag
The LinearNode class holds a reference to
an element (data) and a reference to the
next node in the list
We continue to use an integer variable to
keep track of the number of elements in
the collection
The reference variable contents is a
reference to the head of the linked list of
nodes storing the elements in the bag
collection
6/11/09
javafoundations.LinearNode
//************************************************************
// LinearNode.java Java Foundations
//
// Represents a node in a linked list.
//************************************************************
package javafoundations;
public class LinearNode<T>
{
private LinearNode<T> next;
private T element;
//-----------------------------------------------------------------
// Creates an empty node.
//-----------------------------------------------------------------
public LinearNode()
{
next = null;
element = null;
}
(more…)
6/11/09
javafoundations.LinearNode
//-----------------------------------------------------------------
// Creates a node storing the specified element.
//-----------------------------------------------------------------
public LinearNode (T elem)
{
next = null;
element = elem;
}
//-----------------------------------------------------------------
// Returns the node that follows this one.
//-----------------------------------------------------------------
public LinearNode<T> getNext()
{
return next;
}
//-----------------------------------------------------------------
// Sets the node that follows this one.
//-----------------------------------------------------------------
public void setNext (LinearNode<T> node)
{
next = node;
}
(more…)
6/11/09
javafoundations.LinearNode
//-----------------------------------------------------------------
// Returns the element stored in this node.
//-----------------------------------------------------------------
public T getElement()
{
return element;
}
//-----------------------------------------------------------------
// Sets the element stored in this node.
//-----------------------------------------------------------------
public void setElement (T elem)
{
element = elem;
}
}
6/11/09
javafoundations.LinkedBag
//**************************************************************
// LinkedBag.java Java Foundations
//
// Represents a linked implementation of a bag collection.
//**************************************************************
package javafoundations;
import java.util.*;
import javafoundations.exceptions.EmptyCollectionException;
public class LinkedBag<T> implements Bag<T>
{
private int count = 0;
private LinearNode<T> contents;
private static Random rand = new Random();
//-----------------------------------------------------------------
// Creates an empty list.
//-----------------------------------------------------------------
public LinkedBag()
{
count = 0;
contents = null;
}
(more…)
6/11/09
javafoundations.LinkedBag
//-----------------------------------------------------------------
// Removes a random element from this bag. Throws an
// EmptyCollectionException if this bag is empty.
//-----------------------------------------------------------------
public T remove() throws EmptyCollectionException
{
T result = null;
if (count == 0)
throw new EmptyCollectionException ("Remove operation "
+ "failed. The bag is empty.");
int choice = rand.nextInt(count) + 1;
if (choice == 1)
{
result = contents.getElement();
contents = contents.getNext();
}
else
{
LinearNode<T> current = contents;
for (int i=1; i < choice-1; i++)
current = current.getNext();
result = current.getNext().getElement();
current.setNext(current.getNext().getNext());
}
(more…)
6/11/09
javafoundations.LinkedBag
//-----------------------------------------------------------------
// Adds the specified element to this bag by putting it on the
// front of the list.
//-----------------------------------------------------------------
public void add (T element)
{
LinearNode<T> node = new LinearNode<T>(element);
node.setNext(contents);
contents = node;
count++;
}
//-----------------------------------------------------------------
// Returns an iterator for this bag.
//-----------------------------------------------------------------
public Iterator<T> iterator()
{
ArrayIterator<T> iter = new ArrayIterator<T>();
LinearNode<T> current = contents;
while (current != null)
{
iter.add(current.getElement());
current = current.getNext();
}
return iter;
}
(more…)
6/11/09
javafoundations.LinkedBag
//-----------------------------------------------------------------
// The following methods are left as programming projects.
//-----------------------------------------------------------------
// public boolean isEmpty() { }
// public int size() { }
// public String toString() { }
}
6/11/09
Summary
This week we focused on
the concept of a collection
the importance of separating the interface
from the implementation
generic types and their use in collection
classes
the difference between fixed and dynamic
implementations
dynamically linked lists
the Java Collections API
Students also viewed