Please send questions to
st10@humboldt.edu .
/* Cs132ArrayList.java 1.0 */
/* by Sharon Tuttle */
/* last modified: 3-7-03 */
/* */
/* A concrete subclass of Cs132AbstractList, */
/* using an array-based implementation */
public class Cs132ArrayList extends Cs132AbstractList
{
/*------------------------------------
fields
-------------------------------------*/
// array containing list data
private Object data[];
// number of items currently in list
private int count;
// amount to "increment" array, when necessary
static final int INCR_AMT = 10;
/*--------------------------------------
constructors
---------------------------------------*/
// creates an empty list
public Cs132ArrayList()
{
this.data = new Object[INCR_AMT];
this.count = 0;
}
/*-------------------------------------------------------
accessors
-------------------------------------------------------*/
/* public Cs132ListNode getData()
{
return this.data;
}
*/
/*-------------------------------------------------------
modifiers
-------------------------------------------------------*/
/* public void setHead(Cs132ListNode newHead)
{
this.head = newHead;
}
*/
/*------------------------------------------
overridden methods
-------------------------------------------*/
public String toString()
{
String elementString = "";
for(int i = 0; i < this.size(); i++)
{
elementString = elementString + this.data[i] + "\n";
}
return "Cs132ArrayList[size = " + this.count + ", elements are:\n"
+ elementString
+ "]";
}
/*---------------------------------------
other methods
----------------------------------------*/
/*-----------------------------------------------------------
isEmpty()
Purpose: return true if this list contains no elements, return
false otherwise.
Hey --- why don't I just inherit this from Cs132AbstractList?
-----------------------------------------------------------------*/
/*--------------------------------------------------------
size
Purpose: return current size of the list
(why not make this an accessor? Well, I'd like to hide
the implementation detail count --- but, whether I
store it or not, finding the size of a list is a useful
piece of info for many lists.)
----------------------------------------------------------*/
public int size()
{
return this.count;
}
/*--------------------------------------------------------
expandArrayWhileAdd
Purpose: increase the size of the array when the number
of elements justifies it (that is, when an
addition to the list threatens to overflow it).
(a private, local operation, of course)
-----------------------------------------------------------*/
private void expandArrayWhileAdd(int newElemPos, Object newElement)
{
Object[] newArray = new Object[this.data.length + INCR_AMT];
// copy the elements from the current array to the new,
// bigger array; loop goes 1 time more than usual
// because of the new element being added along the way
int newI = 0;
for (int oldI=0; oldI < this.size()+1; oldI++)
{
// is this where new element is supposed to go?
if (oldI == newElemPos)
{
newArray[newI] = newElement;
newI++; // need extra incrementation this time only...
}
// if new element not at END of array...
if (oldI != this.size())
{
newArray[newI] = this.data[oldI];
newI++;
}
}
// now, THIS should be our new data array
this.data = newArray;
this.count = this.count + 1;
}
/*-------------------------------------------------------
addFirst
Purpose: add given data newObj to beginning
of list.
Hey --- why don't I just inherit that from Cs132AbstractList?
---------------------------------------------------------*/
/*-------------------------------------------------------
addLast()
Purpose: add given data newObj to end
of list.
Hey --- why don't I just inherit this from Cs132AbstractList,
too? Because I can directly implement it more efficiently;
---------------------------------------------------------*/
public void addLast(Object newElement)
{
// will adding the element overflow the array? If so,
// add it in as array is copied into a larger array...
if (this.data.length == this.size())
{
this.expandArrayWhileAdd(this.size(), newElement);
}
// else, we add it in the current array here...
else
{
this.data[this.size()] = newElement;
this.count = this.count + 1;
}
}
/*----------------------------------------------------------------
add()
Purpose: add given data newElement to list at position index (where
0 is the index of the first item in the list, 1 is the
index of the 2nd item in the list, etc.)
Throw a ListIndexOutOfBoundsException if the list
index is not between 0 and the size of the array
(I *could* add a new element to the end --- thus "size"
instead of the usual "size - 1").
BUT note --- those elements "after" this position ARE
shifted "up" a position!
-----------------------------------------------------------------*/
public void add(int index, Object newElement) throws
ListIndexOutOfBoundsException
{
// complain if trying to add an element to an illegal position
if ((index < 0) || (index > this.size()))
{
throw new ListIndexOutOfBoundsException(index);
}
// if get here, index is reasonable.
// will adding the element overflow the array? If so,
// add it in as array is copied into a larger array...
if (this.data.length == this.size())
{
this.expandArrayWhileAdd(index, newElement);
}
// else, we add it in the current array here...
else
{
// shift down everything from position index to the end
for (int i = this.size(); i > index; i--)
{
this.data[i] = this.data[i-1];
}
// ...and should be able to add new item now
this.data[index] = newElement;
this.count = this.count+1;
}
}
/*----------------------------------------------------------------
getFirst()
Purpose: IF list is not empty, return FIRST element in list.
(this is its VALUE, not the node itself!)
If it IS empty, throw a ListEmptyException
Let's inherit this from Cs132AbstractList...
-----------------------------------------------------------------*/
/*----------------------------------------------------------------
getLast()
Purpose: IF the list is not empty, return the LAST element in list.
(this is its VALUE, not the node itself!)
If it IS empty, throw a ListEmptyException
Let's inherit this, too.
----------------------------------------------------------------------*/
/*----------------------------------------------------------------
get()
Purpose: return the element at position index in the list
(where 0 is the index of the first item in the list).
If the list is empty, throw a ListEmptyException.
If the index is not between 0 and (list's size - 1),
throw a ListIndexOutOfBoundsException.
---------------------------------------------------------------------*/
public Object get(int index) throws ListEmptyException,
ListIndexOutOfBoundsException
{
// is list empty?
if (this.size() == 0)
{
throw new ListEmptyException();
}
// list is NOT empty, so now
// make sure that index is reasonable --- if not, complain
if ((index < 0) || (index >= this.count))
{
throw new ListIndexOutOfBoundsException(index);
}
// index must be reasonable, if reach here ---
// grab that list element
return this.data[index];
}
/*----------------------------------------------------------------
remove()
Purpose: This seeks to remove the element at position index
of the list (where 0 is the index of
the first element in the list). It will do so and return
the object removed if the index is indeed a position
in the list. (elements "above" in this list are now
one position "lower")
If the list is empty, however, it will
throw a ListEmptyException, and if the index is not
a position in the list, it will throw a
ListIndexOutOfBoundsException.
--------------------------------------------------------------------*/
public Object remove(int index) throws ListEmptyException,
ListIndexOutOfBoundsException
{
// is list empty?
if (this.size() == 0)
{
throw new ListEmptyException();
}
// list is NOT empty, so now
// make sure that index is reasonable --- if not, complain
if ((index < 0) || (index >= this.count))
{
throw new ListIndexOutOfBoundsException(index);
}
// since it is reasonable, can remove it by shifting
// all "above" it "down" one position, and resetting count
Object deletedElement = this.data[index];
for (int i=index; i < this.size()-1 ; i++)
{
this.data[i] = this.data[i+1];
}
this.count = this.count-1;
return deletedElement;
}
/*----------------------------------------------------------------
clear()
Purpose: empties the LinkedList instance that calls this.
----------------------------------------------------------------------*/
public void clear()
{
this.count = 0;
}
}