CH 02
CH 02
8
ArrayList Class
The simplest class that implements the
List interface
An improvement over an array object
Use when:
you will be adding new elements to the end
of a list
you need to access elements quickly in any
order
ArrayList Class (cont.)
To declare a List “object” whose
elements will reference String objects:
List<String> myList = new ArrayList<String>();
myList.remove(1);
myList.set(2, "Sneezy");
ArrayList Class (cont.)
myList.indexOf("Jumpy");
Section 2.2
Example Application of ArrayList
if (index != -1)
dE = theDirectory.get(index);
else
dE = null;
Implementation of an ArrayList
Class
Section 2.3
Implementing an ArrayList Class
/** This class implements some of the methods of the Java ArrayList class
*/
public class KWArrayList<E> {
// Data fields
/** The default initial capacity */
private static final int INITIAL_CAPACITY = 10;
// check bounds
if (index < 0 || index > size) {
throw new ArrayIndexOutOfBoundsException(index);
}
// shift data
for (int i = size; i > index; i--) {
theData[i] = theData[i-1];
}
// insert item
theData[index] = anEntry;
size++;
}
set and get Methods
public E get (int index) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
return theData[index];
}
E returnValue = theData[index];
size--;
return returnValue;
}
reallocate Method
Create a new array that is twice the size
of the current array and then copy the
contents of the new array
private void reallocate () {
capacity *= 2;
theData = Arrays.copyOf(theData, capacity);
}
reallocate Method (cont.)
private void reallocate () {
capacity *= 2;
theData = Arrays.copyOf(theData, capacity);
}
tom.next = dick;
dick.next = harry;
harry.next = sam;
A Single-Linked List
Class
Generally, we do not have individual
references to each node.
A SingleLinkedList object has a data
field head, the list head, which
references the first list node
Node<String>
next =
data = "Ann"
The element
added to the list
Implementing SLList.addFirst(E item) (cont.)
Node<String>
next =
data = "Ann"
The element
added to the list
Implementing addAfter(Node<E> node, E item)
(cont.)
private void addAfter (Node<E> node, E item) {
Node<E> temp = new Node<E>(item, node.next);
node.next = temp; We declare this method
size++; private since it should not
be called from outside the
} class. Later we will see
how this method is used to
implement the public add
or, more simply ... methods.
Node<String>
The Node
parameter next =
data = "Ann"
Implementing removeAfter(Node<E> node)
(cont.)
private E removeAfter (Node<E> node) {
Node<E> temp = node.next;
if (temp != null) {
node.next = temp.next;
size--;
return temp.data;
} else {
return null;
}
}
Implementing
SLList.removeFirst()
SLList<String> Node<String>
head = next =
data = "Dick"
Node<String>
next =
temp data = "Tom"
Implementing SLList.removeFirst()
(cont.)
private E removeFirst () {
Node<E> temp = head;
if (head != null) {
head = head.next;
}
if (temp != null) {
size--;
return temp.data
} else {
return null;
}
}
Traversing a Single-
Linked List
Do
something
with nodeRef Node<String>
nodeRef
next = null
data = "Ann"
Traversing a Single-Linked List
(cont.)
toString()can be implemented with a traversal:
nodeRef = nodeRef.next;
}
}
SLList.getNode(int)
In order to implement methods required
by the List interface, we need an
additional helper method:
IndexOutOfBoundsException(Integer.toString(index));
}
Node<E> node = getNode(index);
E result = node.data;
node.data = anEntry;
return result;
}
public void add(int index, E item)
head.data = lastNode.data;
lastNode.data = first;
}
}
public void removeMiddle()
public void removeMiddle () {
if (size %2==1) {
if(size >=1){
int middle = size/2;
remove(middle);
}
}
else{
if(size >=2){
int middle1 = size/2;
int middle2 = middle1-1; // size/2 - 1
remove(middle1);
remove(middle2);
}
}
}
public int indexOfMin()
public int indexOfMin () {
Node<E> node = head;
E min = head.data;
int indexMin=0; index =0 ;
while(node !=null){
if( node.data < min){
min = node.data;
indexMin = index;
}
node = node.next;
index++;
}
return indexMin;
}
public void indexOfMax()
public int indexOfMax () {
Node<E> node = head;
E max = head.data;
int indexMax = 0; index =0 ;
while(node !=null){
if( node.data > max){
max = node.data;
indexMax = index;
}
node = node.next;
index++;
}
return indexMax;
}
public void swapMinMax()
public void swapMinMax () {
if (size > =2) {
int minIndex = indexOfMin();
int maxIndex = indexOfMax();
E min= get(minIndex);
E max = get(maxIndex);
set(minIndex, max);
set(maxIndex, min);
}
}
Double-Linked Lists and Circular
Lists
Section 2.6
Double-Linked Lists
Limitations of a singly-linked list include:
Insertion at the front is O(1); insertion at
other positions is O(n)
Insertion is convenient only after a
referenced node
Removing a node requires a reference to
the previous node
We can traverse the list only in the forward
direction
We can overcome these limitations:
Add a reference in each node to the
Double-Linked Lists
(cont.)
Node Class
private static class Node<E> {
private E data;
private Node<E> next = null;
private Node<E> prev = null;
Node Node
sharon
Node<E> sharon = new Node<E>("Sharon");
sharon.next = sam;
sharon.prev = sam.prev; Node
sam.prev.next = sharon;
sam.prev = sharon next =
= prev
data = "Sharon"
Removing from a Double-Linked List
harry
Node Node
next = next =
= prev = prev
data = "Dick" data = "Sharon"
Node
next =
harry.prev.next = harry.next = prev
harry.next.prev = harry.prev data = "Harry"
A Double-Linked List
Class
So far we have worked only
with internal nodes
As with the single-linked class,
it is best to access the internal
nodes with a double-linked list
object
A double-linked list object has data fields:
head (a reference to the first list Node)
tail (a reference to the last list Node)
size
Insertion at either end is O(1); insertion
elsewhere is still O(n)
public Node<E> minNode()
public Node<E> minNode () {
Node<E> node = head;
Node<E> minNode = head;
E min = head.data;
while(node !=null){
if( node.data < min){
min = node.data;
minNode = node;
}
node = node.next;
}
return minNode;
}
public Node<E> minNode()
public Node<E> minNode () {
Node<E> minNode = head;
Node<E> temp = head;
E min = head.data;
while(temp !=null){
if( temp.data < min){
min = temp.data;
minNode = temp;
}
temp = temp.next;
}
return minNode;
}
public void removeMinNode()
public void removeMinNode () {
Node<E> minNode = minNode ();
Node<E> p = minNode.prev;
Node<E> q = minNode.next;
if(tail == head){ tail = null; head =null; size=0;}
else if(minNode.prev ==null){
head = head.next;
head.prev = null; size--;
}
else if(minNode.next ==null){
tail = tail.prev;
tail.next = null; size--;
}
else{
p.next = q;
q.prev = p; size--;
}
}
Circular Lists
Circular double-linked list:
Link last node to the first node, and
Link first node to the last node
We can also build singly-linked circular lists:
Traverse in forward direction only
Advantages:
Continue to traverse even after passing the first or
last node
Visit all elements from any starting point
Never fall off the end of a list
Disadvantage: Code must avoid an infinite loop!
Circular Lists (cont.)
The LinkedList Class and the Iterator,
ListIterator, and Iterable Interfaces
Section 2.7
The LinkedList Class
The Iterator
An iterator can be viewed as a moving place
marker that keeps track of the current position in
a particular linked list
An Iterator object for a list starts at the first
node
The programmer can move the Iterator by
calling its next method
The Iterator stays on its current list item until it
is needed
An Iterator traverses in O(n) while a list
traversal using get() calls in a linked list is O(n2)
Iterator Interface
The Iterator interface is defined in
java.util
The List interface declares the method
iterator which returns an Iterator
object that iterates over the elements of
that list
Iterator Interface (cont.)
An Iterator is conceptually between
elements; it does not refer to a particular
object at any given time
Iterator Interface (cont.)
In the following loop, we process all
items in List<Integer> through an
Iterator
count = 0;
for (String nextStr : myList) {
if (target.equals(nextStr)) {
count++;
}
}
Enhanced for Statement
(cont.)
In list myList of type LinkedList<Integer>,
each Integer object is automatically
unboxed:
sum = 0;
for (int nextInt : myList) {
sum += nextInt;
}
Enhanced for Statement
(cont.)
The enhanced for statement also can be
used with arrays, in this case, chars or
type char[]
. . .
Add Method
1. Obtain a reference, /** Add an item at the specified
nodeRef, to the node at index.
position index @param index The index at
which the object is
2. Insert a new Node to be inserted
containing obj before the @param obj The object to be
node referenced by inserted
nodeRef @throws
IndexOutOfBoundsException
To use a ListIterator object to if the index is out
implement add: of range
3. Obtain an iterator that is (i < 0 || i > size())
It is not necessary to
positioned just before the */
declare a local
Node at position index public void add(int index, E obj)
ListIterator; the {
4. Insert a new Node
method call listIterator(index).add(obj);
containing obj before the
listIterator returns an }
Node currently referenced
anonymous
by this iterator
listIterator object
Get Method
1. Obtain a reference, /** Get the element at position
index.
nodeRef, to the @param index Position of
node at position item to be retrieved
index @return The item at index
*/
2. Return the contents
public E get(int index) {
of the Node return
referenced by listIterator(index).next();
nodeRef }
Other Add and Get
Methods
public void addFirst(E item) {
add(0, item);
}
public E getFirst() {
return head.data;
}
public E getLast() {
return tail.data;
}
Implementing the ListIterator
Interface
KWListIteris an inner class of KWLinkedList
which implements the ListIterator
interface
Implementing the ListIterator
Interface (cont.)
Implementing the ListIterator
Interface (cont.)
KWListIter
public E next() {
if (!hasNext()) {
nextItem throw new NoSuchElementException();
lastItemReturned }
index 12 lastItemReturned = nextItem;
nextItem = nextItem.next;
index++;
return lastItemReturned.data;
}
Previous Methods
public boolean hasPrevious() {
return (nextItem == null && size != 0)
|| nextItem.prev != null;
}
public E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
if (nextItem == null) { // Iterator past the last element
nextItem = tail;
}
else {
nextItem = nextItem.prev;
}
lastItemReturned = nextItem;
index--;
return lastItemReturned.data;
}
The Add Method
When adding, there are four cases to
address:
Add to an empty list
Add to the head of the list
Add to the tail of the list
Add to the middle of the list
Adding to an Empty List
(after insertion)
if (head == null) {
head = new Node<E>(obj);
tail = head;
}
...
size++
Adding to the
Head of the
KWListIter
List
nextItem =
lastItemReturned = null
1
index = 0
Node Node Node
head = null
tail = null
4
size = 3
head = null
tail = null
4
size = 3
Node
else {
Node<E> newNode = new Node<E>(obj); next = null
newNode.prev = nextItem.prev; null = prev
nextItem.prev.next = newNode; data = "Bob"
newNode.next = nextItem;
nextItem.prev = newNode;
} newNode
...
size++;
index++;
Inner Classes: Static and Nonstatic
Section 2.9
The Collection Interface
Specifies a subset of methods in the List
interface, specifically excluding
add(int, E)
get(int)
remove(int)
set(int, E)
but including
add(E)
remove(Object)
the iterator method
The Collection
Framework
Common Features of
Collections
Collections
grow as needed
hold references to objects
have at least two constructors: one to
create an empty collection and one to make
a copy of another collection
Common Features of Collections
(cont.)
Extend AbstractList<E>
You need to implement only:
add(int, E)
get(int)
remove(int)
set(int, E)
size()
AbstractList implements Iterator<E>
using the index
AbstractCollection, AbstractList,
and AbstractSequentialList
Another more complete way to declare
KWArrayList is:
Section 2.10
An Application: Ordered
Lists
We want to maintain a list of names in
alphabetical order at all times
Approach
Develop an OrderedList class (which can be
used for other applications)
Implement a Comparable interface by providing
a compareTo(E) method
Use a LinkedList class as a component of the
OrderedList
if OrderedList extended LinkedList, the user could
use LinkedList's add methods to add an element
out of order
Class Diagram for
OrderedList
Design
Inserting into an
OrderedList
Strategy for inserting new element e:
Find first item > e
Insert e before that item
Refined with an iterator:
Create ListIterator that starts at the
beginning of the list
While the ListIterator is not at the end of the
list and e >= the next item
Advance the ListIterator
Insert e before the current ListIterator
position
Inserting Diagrammed
Inserting Diagrammed
(cont.)
OrderedList.add
public void add (E e) {
ListIterator<E> iter = theList.listIterator();
while (iter.hasNext()) {
if (e.compareTo(iter.next()) < 0) {
// found element > new one
iter.previous(); // back up by one
iter.add(e); // add new one
return; // done
}
}
iter.add(e); // will add at end
}
Using Delegation to Implement the
Other Methods