diff --git a/.idea/misc.xml b/.idea/misc.xml
index 07115cd..03f397c 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
index 3e59c38..51c098b 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,5 +1,325 @@
+import edu.greenriver.sdev333.*;
+
+import java.util.ListIterator;
+
+/**
+ * Did the Level 1, Level 2, and Extras with the exception of the
+ * hashCode() method.
+ *
+ * Main Class used to test functionality of ArrayList implementation.
+ * Inside the main() method are comments and code regarding the setup
+ * and testing for each given method.
+ *
+ * @author Paul Woods
+ */
public class Main {
+
+ /*
+ * private method to print our list, utilizes the Iterator
+ * via a for-each loop to do so.
+ */
+ private static void printIntList(List l) {
+ for(int i: l) {
+ System.out.print(i + " ");
+ }
+ System.out.println();
+ }
+
+ /**
+ * Our main method where we have our testing for our List
+ * classes.
+ * @param args
+ */
public static void main(String[] args) {
- System.out.println("Hello world!");
+
+ System.out.println();
+ System.out.println("Create list of integers, adding 10 elements, 1 .. 10");
+ //List intList = new ArrayList<>();
+ List intList = new DoublyLinkedList<>();
+
+ System.out.println("testing isEmpty on empty list, returns: " + intList.isEmpty());
+
+ // tests .add()
+ intList.add(1);
+ intList.add(2);
+ intList.add(3);
+ intList.add(4);
+ intList.add(5);
+ intList.add(6);
+ intList.add(7);
+ intList.add(8);
+ intList.add(9);
+ intList.add(10);
+ printIntList(intList);
+/*
+ System.out.println("removing index 5 (#6)");
+ intList.remove(5);
+ printIntList(intList);
+
+ System.out.println("removing index 0 (#1)");
+ intList.remove(0); // remove index
+ printIntList(intList);
+
+ System.out.println("removing item 2");
+ intList.remove(Integer.valueOf(2)); // remove item - problem w/ iterator after this point
+ printIntList(intList);
+
+ System.out.println("removing item 7");
+ intList.remove(Integer.valueOf(7));
+ printIntList(intList);
+
+ System.out.println("Clearing list, then adding numbers 21..25");
+ intList.clear();
+
+ intList.add(21);
+ intList.add(22);
+ intList.add(23);
+ intList.add(24);
+ intList.add(25);
+ printIntList(intList);
+
+ // BEGIN TEST ITERATOR
+ System.out.println("Testing ListIterator forward");
+ ListIterator myItr = intList.listIterator();
+ while(myItr.hasNext()) {
+ System.out.print(myItr.next() + " ");
+ }
+ System.out.println();
+
+ System.out.println("Testing in reverse");
+ while(myItr.hasPrevious()) {
+ System.out.print(myItr.previous() + " ");
+ }
+ System.out.println();
+ // END TEST ITERATOR
+ */
+
+ // NEW FOR DOUBLYLINKEDARRAYLIST
+// System.out.println("Printing List organically w/o iterator");
+// for (int i = 0; i < intList.size(); i++) {
+// System.out.print(intList.get(i) + " ");
+// }
+// System.out.println();
+ // END NEW TEST
+
+ System.out.println("testing isEmpty on a list with 10 items, returns: " + intList.isEmpty());
+ System.out.println();
+ System.out.println("Testing get(0):, should return 1: " + intList.get(0));
+ System.out.println();
+ System.out.println("testing contains(), looking for int value 5");
+ System.out.println("result of contains(Integer.valueOf(5)): " + intList.contains(Integer.valueOf(5)));
+ System.out.println("testing contains(), looking for int value of 90");
+ System.out.println("result of contains(Integer.valueOf(90)): " + intList.contains(Integer.valueOf(90)));
+ System.out.println();
+
+ System.out.println("Printing list while testing .iterator() ...");
+ // tests .iterator()
+ printIntList(intList);
+ System.out.println();
+
+ // test .add() again
+ System.out.println("Adding 20 to list");
+ intList.add(20);
+ System.out.println("Size: " + intList.size());
+ printIntList(intList);
+ System.out.println();
+
+ // test .set(index, value)
+ System.out.println("Setting index 8 (#9) to 90");
+ intList.set(8, 90);
+ System.out.println("Size: " + intList.size());
+ printIntList(intList);
+ System.out.println();
+
+ // test .add(index, value)
+ System.out.println("Adding 40 at index 4");
+ intList.add(4,40);
+ System.out.println("Size: " + intList.size());
+ printIntList(intList);
+ System.out.println();
+
+ // test .indexOf(val)
+ System.out.println("Testing indexOf(item), index of 90 should be 9.");
+ System.out.println(intList.indexOf(90));
+ System.out.println();
+
+ // test .indexOf(val)
+ System.out.println("Testing indexOf(item), index of 3 should be 2.");
+ System.out.println(intList.indexOf(3));
+ System.out.println();
+
+ // add 5 again, and reprint list
+ System.out.println("Adding 5 to end of list for next test");
+ intList.add(5);
+ printIntList(intList);
+ System.out.println();
+
+ // test .lastIndexOf(val)
+ System.out.println("Finding last index of 5, should be 12");
+ System.out.println("Calculated lastIndex of 5: " + intList.lastIndexOf(5));
+ System.out.println("Finding last index of 40, should be 4");
+ System.out.println("Calculated lastIndex of 40: " + intList.lastIndexOf(40));
+ System.out.println();
+
+ printIntList(intList);
+
+ // testing remove(index)
+ System.out.println("Testing remove(index), removing index 4 (#40)");
+ intList.remove(4);
+ printIntList(intList);
+ System.out.println();
+
+ // test containsAll()
+ List newList = new DoublyLinkedList<>();
+ newList.add(1);
+ newList.add(8);
+ System.out.println("Testing containsAll() with a sublist of 1 and 8, should return true");
+ System.out.println("containsAll() result: " + intList.containsAll(newList));
+ newList.add(999);
+ System.out.println("Testing containsAll() with a sublist of 1, 8, and 999 should return false");
+ System.out.println("containsAll() result: " + intList.containsAll(newList));
+ printIntList(intList);
+ System.out.println();
+
+ // tests removeItem(item)
+ System.out.println("Testing remove(item), removing #90");
+ intList.remove(Integer.valueOf(90));
+ // NOTE - Use the Integer.valueOf() static method to remove a value as from ArrayList
+
+ printIntList(intList);
+ System.out.println();
+
+ // test clear()
+ System.out.println();
+ System.out.println("Testing clear(), printed list");
+ intList.clear();
+ printIntList(intList);
+ System.out.println();
+
+ // testing 2nd constructor w/ initial parameter
+ intList = new DoublyLinkedList<>();
+ intList.add(1);
+ intList.add(2);
+ intList.add(3);
+ intList.add(4);
+ intList.add(5);
+ intList.add(6);
+ intList.add(7);
+ intList.add(8);
+ intList.add(9);
+ intList.add(10);
+ System.out.println("Testing 2nd constructor w/ initial size parameter, should have 1..10 entered.");
+ System.out.println("Note, no 2nd constructor for DoublyLinkedList, using original ... ");
+ printIntList(intList);
+ System.out.println();
+
+ // testing addAll(collection)
+ List tempList = new DoublyLinkedList<>();
+ tempList.add(50);
+ tempList.add(51);
+ tempList.add(52);
+ tempList.add(53);
+ tempList.add(54);
+ tempList.add(55);
+ System.out.println("Testing addAll(), adding a new collection that contains 50 ... 55 to list");
+ intList.addAll(tempList);
+ printIntList(intList);
+ System.out.println();
+
+ // testing equals() method
+ System.out.println("Testing equals() method, original list vs tempList (50..55), should be false");
+ System.out.println("Result of intList.equals(tempList): " + intList.equals(tempList));
+ System.out.println("Testing equals method, tempList (50..55) vs bList (50..55), should be true");
+ List bList = new DoublyLinkedList<>();
+ bList.add(50);
+ bList.add(51);
+ bList.add(52);
+ bList.add(53);
+ bList.add(54);
+ bList.add(55);
+ System.out.println("Result of tempList.equals(bList): " + tempList.equals(bList));
+
+ System.out.println();
+ System.out.println("Original list again:");
+ printIntList(intList);
+
+
+ // BEGIN TEST ITERATOR
+ System.out.println("Testing ListIterator forward");
+ ListIterator myItr = intList.listIterator();
+ while(myItr.hasNext()) {
+ System.out.print(myItr.next() + " ");
+ }
+ System.out.println();
+
+ System.out.println("Testing in reverse");
+ while(myItr.hasPrevious()) {
+ System.out.print(myItr.previous() + " ");
+ }
+ System.out.println();
+ // END TEST ITERATOR
+
+
+
+ System.out.println();
+
+ List cList = new DoublyLinkedList<>();
+ cList.add(1);
+ cList.add(5);
+ cList.add(9);
+ cList.add(52);
+ cList.add(55);
+ cList.add(72);
+
+ // testing removeAll(collection)
+ System.out.println("Will be removing cList from our original list, cList is:");
+ printIntList(cList);
+ System.out.println("Testing removeAll(collection), removing cList from intList.");
+ intList.removeAll(cList);
+ System.out.println("Resulting list: ");
+ printIntList(intList);
+ System.out.println();
+
+ // testing retainAll()
+ System.out.println("We are going to test retainAll(), but lets add items back to our original list.");
+ System.out.println("Original list again:");
+ intList.addAll(cList);
+
+ cList.add(99);
+ printIntList(intList);
+ System.out.println("cList again is (added 99 to this list):");
+ printIntList(cList);
+ System.out.println("We are going to retain only the items in cList that are in our original list");
+ intList.retainAll(cList);
+ System.out.println("Resulting original list:");
+ printIntList(intList);
+
+ System.out.println("Adding 1..10 to original list again");
+ intList.add(1);
+ intList.add(2);
+ intList.add(3);
+ intList.add(4);
+ intList.add(5);
+ intList.add(6);
+ intList.add(7);
+ intList.add(8);
+ intList.add(9);
+ intList.add(10);
+ printIntList(intList);
+
+ System.out.println("Testing ListIterator forward");
+ //ListIterator myItr = intList.listIterator();
+ myItr = intList.listIterator();
+ while(myItr.hasNext()) {
+ System.out.print(myItr.next() + " ");
+ }
+ System.out.println();
+
+ System.out.println("Testing in reverse");
+ while(myItr.hasPrevious()) {
+ System.out.print(myItr.previous() + " ");
+ }
+ System.out.println();
+
}
}
\ No newline at end of file
diff --git a/src/edu/greenriver/sdev333/ArrayList.java b/src/edu/greenriver/sdev333/ArrayList.java
new file mode 100644
index 0000000..d31c5cb
--- /dev/null
+++ b/src/edu/greenriver/sdev333/ArrayList.java
@@ -0,0 +1,529 @@
+package edu.greenriver.sdev333;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * This class implements the List interface in the Java collections
+ * package. The individual public methods are tested in the
+ * corresponding Main class, with comments there regarding each
+ * method tested.
+ *
+ * Implemented and tested all listed methods except for hashCode(). I read in
+ * prior class notes from CS145 "If the .equals() method returns true on two objects,
+ * their hashCode() must also return the same value." I am unsure how I can
+ * get two 'equal' lists to return the same hashCode if they have equal objects,
+ * so am going to forgo that method for now.
+ *
+ * @author Paul Woods
+ *
+ * @param
+ */
+public class ArrayList implements List {
+
+ // WE NEED FIELDS
+
+ // one plain Java array
+ private ItemType[] data;
+
+ // one int to keep track of size
+ // size is the number of spots used in the data array
+ // size is different than length
+ private int size;
+
+ public ArrayList() {
+ size = 0;
+ data = (ItemType[]) new Object[10];
+ }
+
+ public ArrayList(int initial) {
+ size = 0;
+ data = (ItemType[]) new Object[initial];
+ }
+
+
+ /**
+ * Returns the number of items in this collection.
+ *
+ * @return the number of items in this collection
+ */
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns true if this collection contains no items.
+ *
+ * @return true if this collection contains no items
+ */
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Returns true if this collection contains the specified item.
+ *
+ * @param item items whose presence in this collection is to be tested
+ * @return true if this collection contains the specified item
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public boolean contains(ItemType item) {
+ if (item == null) {
+ throw new NullPointerException();
+ }
+
+ return (indexOf(item) != -1);
+ }
+
+ /**
+ * Returns an iterator over the elements in this collection.
+ *
+ * @return an Iterator over the elements in this collection
+ */
+ @Override
+ public Iterator iterator() {
+ return new OurCustomIterator();
+ }
+
+ /**
+ * Adds the specified item to the collection.
+ *
+ * @param item item to be added to the collection
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void add(ItemType item) {
+ data[size++] = item;
+
+ // all of the above works until I run out of room when size becomes
+ // the same as length, I'm out of room
+ checkSize();
+
+ }
+
+ /*
+ * check for size increase requirement, and double-array size
+ * if necessary
+ */
+ private void checkSize() {
+ if (size == data.length) {
+ // resize up ....
+
+ // Step 1 - create a temp array 2x size
+ ItemType[] temp = (ItemType[]) new Object[data.length * 2];;
+
+ // Step 2 - copy arrayElements from data to temp
+ for (int i = 0; i < size; i++) {
+ temp[i] = data[i];
+ }
+
+ // Step 3 - point 'data' at temp array
+ data = temp;
+ }
+ }
+
+ /**
+ * Removes a single instance of the specified item from this collection,
+ * if it is present.
+ *
+ * @param item item to be removed from this collection, if present
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void remove(ItemType item) {
+ if (item == null) {
+ throw new NullPointerException();
+ }
+ // IN CLASS
+ int i = indexOf(item);
+ if (i != -1) {
+ remove(i);
+ }
+ }
+
+ /**
+ * Removes all items from this collection.
+ * The collection will be empty after this method returns.
+ */
+ @Override
+ public void clear() {
+ // data = (ItemType[]) new Object[data.length];
+ size = 0;
+ }
+
+ /**
+ * Returns true if this collection contains all the items
+ * in the specified other collection.
+ *
+ * @param otherCollection collection to be checked for containment in this collection
+ * @return true if this collection contains all the items
+ * in the specified other collection
+ */
+ @Override
+ public boolean containsAll(Collection extends ItemType> otherCollection) {
+
+ for (ItemType i: otherCollection) {
+ if (!contains(i))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Adds all the items in this specified other collection to this collection.
+ *
+ * @param otherCollection collection containing items to be added to this collection
+ */
+ @Override
+ public void addAll(Collection extends ItemType> otherCollection) {
+ if (otherCollection != null) {
+ for (ItemType i: otherCollection) {
+ this.add(i);
+ }
+ }
+ }
+
+ /**
+ * Removes all of this collection's items that are also contained in the
+ * specified other collection. After this call returns, this collection will
+ * contain no elements in common with the specified other collection.
+ *
+ * @param otherCollection collection containing elements to be removed
+ * from this collection
+ */
+ @Override
+ public void removeAll(Collection extends ItemType> otherCollection) {
+ for (ItemType i: otherCollection) {
+ remove(i);
+ }
+ }
+
+ /**
+ * Retains only the items in this collection that are contained in the
+ * specified other collection. In other words, removes from this collection
+ * all of its items that are not contained in the specified other collection
+ *
+ * @param otherCollection collection containing elements to be retained in
+ * this collection
+ */
+ @Override
+ public void retainAll(Collection extends ItemType> otherCollection) {
+ // Create a value-copy of current list
+ List listCopy = new ArrayList<>();
+ for (ItemType i: this) {
+ listCopy.add(i);
+ }
+
+ // remove items in otherCollection from listCopy
+ // this leaves us with an inverted view of the list
+ listCopy.removeAll(otherCollection);
+
+ // now remove listCopy items from originalList
+ this.removeAll(listCopy);
+ }
+
+ /**
+ * Returns the item at the specified position in this list
+ *
+ * @param index index of the item to return
+ * @return the item at the specified position in this list
+ * @throws IndexOutOfBoundsException if this index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public ItemType get(int index) {
+ if (validIndex(index)) {
+ return data[index];
+ }
+ else {
+ throw new IndexOutOfBoundsException("index is beyond size");
+ }
+ }
+
+ /**
+ * Replaces the item at the specified position in this list
+ * with the specified item
+ *
+ * @param index index of the item to replace
+ * @param item item to be stored at the specified position
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void set(int index, ItemType item) {
+ if (validIndex(index)) {
+ data[index] = item;
+ } else {
+ throw new IndexOutOfBoundsException("index is beyond size");
+ }
+ }
+
+ /**
+ * Inserts the specified item at the specified position in this list.
+ * Shifts the item currently at that position (if any) and any subsequent
+ * items to the right.
+ *
+ * @param index index at which the specified item is to be inserted
+ * @param item item to be inserted
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void add(int index, ItemType item) {
+ if (validIndex(index)) {
+ // Add the last item to the end of list, and shift everything behind it to the right
+ this.add(data[size-1]);
+
+ for (int i = size-2; i > index; i--) {
+ data[i] = data[i-1];
+ }
+
+ // finally, set the 'added' item to the specified location
+ set(index, item);
+ }
+ }
+
+ /**
+ * Removes the element at the specified position in this list.
+ * Shifts any subsequent items to the left.
+ *
+ * @param index the index of the item to be removed
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void remove(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ for (int i = index; i < size - 1; i++) {
+ data[i] = data[i + 1];
+ }
+
+ size--;
+ }
+
+ /**
+ * Returns the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int indexOf(ItemType item) {
+ // DID AT HOME
+ for (int i = 0; i < size; i++) {
+ if (data[i].equals(item))
+ return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the index of the last occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int lastIndexOf(ItemType item) {
+ for (int i = size-1; i >= 0; i--) {
+ if (data[i].equals(item))
+ return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns a list iterator over the elements in this list
+ * (in proper sequence).
+ *
+ * @return a list iterator over the elements in this list
+ * (in proper sequence)
+ */
+ @Override
+ public ListIterator listIterator() {
+ return new SecondCustomIterator();
+ }
+
+ /**
+ * Per the Oracle javadocs, "... two lists are defined to be equal
+ * if they contain the same elements in the same order."
+ * @param obj object to be compared for equality with this collection
+ * @return
+ */
+ @Override
+ public boolean equals(Object obj) {
+ // Must first ensure these two objects are of the same type ...
+ if (obj != null && obj.getClass() == this.getClass()) {
+
+ // create temporary ArrayList from obj
+ ArrayList temp = (ArrayList) obj;
+
+ // confirm lists are of equal size, if not, return false
+ if (this.size() != temp.size())
+ return false;
+
+ // cycle through individual items, testing one by one
+ // return false if one of pair is not equal
+ for (int i = 0; i < this.size(); i++) {
+ if (this.get(i) != temp.get(i))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * This method tests a given index value to determine if it
+ * is valid. Any index out of range, i.e. smaller than 0
+ * or larger than size, is invalid and does not point to
+ * a valid element.
+ * @param index
+ * @return
+ */
+ private boolean validIndex(int index) {
+ return ((index < this.size) && (index >= 0));
+ }
+
+ /**
+ * This method resizes the array, doubling its previous value, to
+ * make way for new elements. Called as required by various methods.
+ */
+ private void resize() {
+ // Step 1 - create a temp array 2x size
+ ItemType[] temp = (ItemType[]) new Object[data.length * 2];;
+
+ // Step 2 - copy arrayElements from data to temp
+ for (int i = 0; i < size; i++) {
+ temp[i] = data[i];
+ }
+
+ // Step 3 - point 'data' at temp array
+ data = temp;
+ }
+
+ private class OurCustomIterator implements Iterator {
+
+ // fields
+ private int currentPosition;
+
+ public OurCustomIterator() {
+ currentPosition = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return currentPosition < size();
+ }
+
+ @Override
+ public ItemType next() {
+ ItemType result = get(currentPosition);
+ currentPosition++;
+ return result;
+ }
+
+ }
+
+ /**
+ * Implemented methods using primarily same logic as CustomerIterator
+ * above, though the extra methods were completed using documentation found
+ * for the JDK at
+ * https://docs.oracle.com/javase/8/docs/api/java/util/ListIterator.html#previousIndex--
+ */
+ private class SecondCustomIterator implements ListIterator {
+
+ // fancier Iterator that lets us go forwards and backwards
+ private int currentPosition;
+ private int lastIndexReturned;
+
+ public SecondCustomIterator() {
+ currentPosition = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return currentPosition < size();
+ }
+
+ @Override
+ public ItemType next() {
+ ItemType result = get(currentPosition);
+ lastIndexReturned = currentPosition;
+ currentPosition++;
+ return result;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return currentPosition > 0;
+ }
+
+ @Override
+ public ItemType previous() {
+ if (currentPosition > 0) {
+ ItemType result = get(currentPosition - 1);
+ lastIndexReturned = currentPosition - 1;
+ return result;
+ } else {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ public int nextIndex() {
+ if (currentPosition == size() - 1)
+ return currentPosition;
+ else
+ return currentPosition + 1;
+ }
+
+ @Override
+ public int previousIndex() {
+ if (currentPosition == 0)
+ return -1;
+ else
+ return currentPosition - 1;
+ }
+
+ @Override
+ public void remove() {
+ ArrayList.this.remove(lastIndexReturned);
+ }
+
+ @Override
+ public void set(ItemType itemType) {
+ ArrayList.this.set(lastIndexReturned, itemType);
+ }
+
+ @Override
+ public void add(ItemType itemType) {
+
+ }
+ }
+
+} // end of class ArrayList
diff --git a/src/edu/greenriver/sdev333/DoublyLinkedList.java b/src/edu/greenriver/sdev333/DoublyLinkedList.java
new file mode 100644
index 0000000..21c58ae
--- /dev/null
+++ b/src/edu/greenriver/sdev333/DoublyLinkedList.java
@@ -0,0 +1,613 @@
+package edu.greenriver.sdev333;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Did the Level 1, Level 2, and Extras with the exception of the
+ * hashCode() method.
+ *
+ * This class implements the List interface. Testing is done in the
+ * Main class, and there were intial bugs found and then corrected,
+ * esp wrt to the ListIterator class. I had to cycle through the
+ * Main tests comment them out to determine what was interfering
+ * with my list of Nodes (was remove(item)).
+ *
+ * @author Paul Woods
+ */
+public class DoublyLinkedList implements List{
+
+ private Node head;
+ private int size;
+
+ // helper/inner class
+ private class Node {
+ ItemType data;
+ Node next;
+ Node previous;
+ }
+
+ /*
+ * Test w/ for-each statemenet
+ */
+ private class OurCustomIterator implements Iterator {
+
+ private Node iHead;
+
+ public OurCustomIterator() {
+ //iHead = DoublyLinkedList.this.head;
+ iHead = head;
+ }
+ @Override
+ public boolean hasNext() {
+ // Ken tested for if (currentPostition != null) ... but he had reversed the two lines in next() as well
+ //return iHead.next != null;
+ if ((iHead != null) && iHead.next != null)
+ return true;
+ return false;
+ }
+
+ /*
+ * Ken had iHead.next and result = lines reversed
+ */
+ @Override
+ public ItemType next() {
+ iHead = iHead.next;
+ ItemType result = (ItemType) iHead.data;
+ return result;
+ }
+ }
+
+ // geeksforgeeks.org/difference-between-an-iterator-and-listiterator-in-java/
+ private class OurListIterator implements ListIterator {
+
+ private Node iHead;
+ private Node priorNode;
+
+ public OurListIterator() {
+ iHead = head;
+ }
+ @Override
+ public boolean hasNext() {
+ return iHead.next != null;
+ }
+
+ @Override
+ public ItemType next() {
+ iHead = iHead.next;
+ ItemType result = (ItemType) iHead.data;
+ priorNode = iHead;
+ return result;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ //return iHead.previous != null;
+ //return iHead.previous != null;
+ return iHead != null;
+ }
+
+ @Override
+ public ItemType previous() {
+ //iHead = iHead.previous;
+ //ItemType result = (ItemType) iHead.data;
+ ItemType result = (ItemType) iHead.data;
+ //if (iHead.previous != null)
+ iHead = iHead.previous;
+ priorNode = iHead;
+ return result;
+ }
+
+ @Override
+ public int nextIndex() {
+ if (iHead.next == null)
+ return size();
+
+ ItemType next = next();
+ Node node = head;
+ int i = 0;
+
+ while (node.next != null) {
+ node = node.next;
+ i++;
+ if (node.next.data.equals(next)) {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ @Override
+ public int previousIndex() {
+ if (iHead.previous == null)
+ return -1;
+
+ ItemType prev = (ItemType) iHead.previous.data;
+ Node node = head;
+ int i = -1;
+
+ while (node.next != null) {
+ node = node.next; // will be head node w/ index 0 to start
+ i++;
+ if (node.data.equals(prev)) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ @Override
+ public void remove() {
+ // both prior and next nodes ARE NOT null
+ if (priorNode.previous != null && priorNode.next != null) {
+ priorNode.previous.next = priorNode.next; // prior nodes' next value = next node
+ priorNode.next.previous = priorNode.previous;
+ }
+ // both prior and next nodes ARE null (single item in list)
+ else if (priorNode.previous == null && priorNode.next == null) {
+ iHead.next = null;
+ }
+ // prior only IS NULL (1st item in list)
+ else if (priorNode.previous == null) {
+ iHead = priorNode.next;
+ }
+ // next only IS NULL (last item in list)
+ else if (priorNode.next == null) {
+ priorNode.next = null;
+ }
+ }
+
+ @Override
+ public void set(ItemType itemType) {
+
+ }
+
+ @Override
+ public void add(ItemType itemType) {
+
+ }
+ }
+
+ /*
+ * Return a pointer to the last element in the linked-list
+ */
+ private Node getLastElement() {
+ if (size == 0) {
+ return null;
+ } else {
+ Node n = head;
+ while (n.next != null) {
+ n = n.next;
+ }
+ return n;
+ }
+ }
+
+ /*
+ * could have been left inside getElementN, but broken into a separate method for use
+ * by other methods if required
+ */
+ private void validateIndex(int index) {
+ if ((index >= size) || (index < 0))
+ throw new IndexOutOfBoundsException();
+ }
+
+ /*
+ * Return element at index n (not the data in that element)
+ */
+ private Node getElementN(int index) {
+
+ validateIndex(index);
+
+ Node n = head;
+ int i = -1;
+
+ while (n.next != null) {
+ i++;
+ n = n.next;
+ if (i == index) {
+ //System.out.println("data, " + n.data);
+ return n;
+ }
+ }
+
+ // we shouldn't be here ...
+ throw new NullPointerException();
+ }
+
+ public DoublyLinkedList() {
+ // A new list contains no elemenets, so its head is null
+ head = null;
+ size = 0;
+ }
+
+ /**
+ * Returns the number of items in this collection.
+ *
+ * @return the number of items in this collection
+ */
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns true if this collection contains no items.
+ *
+ * @return true if this collection contains no items
+ */
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Returns true if this collection contains the specified item.
+ *
+ * @param item items whose presence in this collection is to be tested
+ * @return true if this collection contains the specified item
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public boolean contains(ItemType item) {
+
+ if (size == 0)
+ return false;
+
+ return indexOf(item) != -1;
+ }
+
+ /**
+ * Returns an iterator over the elements in this collection.
+ *
+ * @return an Iterator over the elements in this collection
+ */
+ @Override
+ public Iterator iterator() {
+ return new OurCustomIterator<>();
+ }
+
+ /**
+ * Adds the specified item to the collection.
+ *
+ * @param item item to be added to the collection
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void add(ItemType item) {
+
+ if (head == null) { // Add new 1st item, item.previous = null
+ head = new Node();
+ head.next = new Node();
+ head.next.data = item;
+ } else {
+ Node currentLast = getLastElement();
+
+ currentLast.next = new Node();
+ currentLast.next.data = item;
+ currentLast.next.previous = currentLast;
+ }
+
+ ++size;
+ }
+
+ /**
+ * Compares the specified object (a collection) with this collection for equality.
+ *
+ * Equal only if the lists are the same size, and each node equals the matching
+ * node in the alternate list.
+ *
+ * @param obj object to be compared for equality with this collection
+ * @return true if the specified other object is equal to this collection
+ */
+ @Override
+ public boolean equals(Object obj) {
+ // https://docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html#equals(java.lang.Object)
+ // object is not null, and it matches this class type
+ if (obj != null && obj.getClass() == this.getClass()) {
+
+ List list = (List) obj;
+
+ if (this.size != list.size())
+ return false;
+
+ ListIterator litA = this.listIterator();
+ ListIterator litB = list.listIterator();
+ while (litA.hasNext()) {
+ if (!litA.next().equals(litB.next()))
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Removes a single instance of the specified item from this collection,
+ * if it is present.
+ *
+ * @param item item to be removed from this collection, if present
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void remove(ItemType item) {
+ if (item == null)
+ throw new NullPointerException();
+
+ Node n = head;
+
+ // 1st Node is treated differently as it has no valid previous
+ if (n.next.data.equals(item)) {
+ n.next = n.next.next;
+ n.next.previous = null;
+ --size;
+ }
+ else {
+ while (n.next != null) {
+ n = n.next;
+ if (n.data.equals(item)) {
+ if (n.next != null)
+ n.next.previous = n.previous; // assign 'previous' for following node to prior node
+ n.previous.next = n.next; // assign 'next' for prior node to n.next
+ --size;
+ return;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Removes all items from this collection.
+ * The collection will be empty after this method returns.
+ */
+ @Override
+ public void clear() {
+ head = null;
+ size = 0;
+ }
+
+ /**
+ * Returns true if this collection contains all the items
+ * in the specified other collection.
+ *
+ * @param otherCollection collection to be checked for containment in this collection
+ * @return true if this collection contains all the items
+ * in the specified other collection
+ */
+ @Override
+ public boolean containsAll(Collection extends ItemType> otherCollection) {
+ // Cycle through otherCollection, and when find an element from that
+ // collection here, remove it. If at some point we do not find one of those
+ // elements, return false. If we make it through the list, return true
+ for (ItemType i: otherCollection) {
+ if (!this.contains(i))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Adds all the items in this specified other collection to this collection.
+ *
+ * @param otherCollection collection containing items to be added to this collection
+ */
+ @Override
+ public void addAll(Collection extends ItemType> otherCollection) {
+ if (otherCollection != null) {
+ for (ItemType i: otherCollection) {
+ this.add(i);
+ }
+ }
+ }
+
+ /**
+ * Removes all of this collection's items that are also contained in the
+ * specified other collection. After this call returns, this collection will
+ * contain no elements in common with the specified other collection.
+ *
+ * @param otherCollection collection containing elements to be removed
+ * from this collection
+ */
+ @Override
+ public void removeAll(Collection extends ItemType> otherCollection) {
+ if (otherCollection != null) {
+ for (ItemType i: otherCollection) {
+ this.remove(i);
+ }
+ }
+ }
+
+ /**
+ * Retains only the items in this collection that are contained in the
+ * specified other collection. In other words, removes from this collection
+ * all of its items that are not contained in the specified other collection
+ *
+ * @param otherCollection collection containing elements to be retained in
+ * this collection
+ */
+ @Override
+ public void retainAll(Collection extends ItemType> otherCollection) {
+ // Create a value-copy of current list
+ List listCopy = new ArrayList<>();
+ for (ItemType i: this) {
+ listCopy.add(i);
+ }
+
+ // remove items in otherCollection from listCopy
+ // this leaves us with an inverted view of the list
+ listCopy.removeAll(otherCollection);
+
+ // now remove listCopy items from originalList
+ this.removeAll(listCopy);
+ }
+
+ /**
+ * Returns the item at the specified position in this list
+ *
+ * @param index index of the item to return
+ * @return the item at the specified position in this list
+ * @throws IndexOutOfBoundsException if this index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public ItemType get(int index) {
+ return getElementN(index).data;
+ }
+
+ /**
+ * Replaces the item at the specified position in this list
+ * with the specified item
+ *
+ * @param index index of the item to replace
+ * @param item item to be stored at the specified position
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void set(int index, ItemType item) {
+ if (item == null)
+ throw new NullPointerException();
+
+ Node i = getElementN(index);
+ i.data = item;
+ }
+
+ /**
+ * Inserts the specified item at the specified position in this list.
+ * Shifts the item currently at that position (if any) and any subsequent
+ * items to the right.
+ *
+ * @param index index at which the specified item is to be inserted
+ * @param item item to be inserted
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void add(int index, ItemType item) {
+ if (item == null)
+ throw new NullPointerException();
+
+ Node i = getElementN(index); // current element at index
+ Node n = new Node(); // new node to be inserted
+ n.data = item;
+ if (index != 0)
+ n.previous = i.previous; // previous value for new node
+ n.next = i; // next value for new node
+ i.previous.next = n; // next value for old prior node
+ i.previous = n; // previous value for old node
+
+ ++size;
+ }
+
+ /**
+ * Removes the element at the specified position in this list.
+ * Shifts any subsequent items to the left.
+ *
+ * @param index the index of the item to be removed
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void remove(int index) {
+ Node i = getElementN(index);
+
+ if (index == 0) {
+ head.next = i.next;
+ i.next.previous = null;
+ } else {
+ i.previous.next = i.next;
+ i.next.previous = i.previous;
+ }
+
+ --size;
+ }
+
+ /**
+ * Returns the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int indexOf(ItemType item) {
+ if (item == null)
+ throw new NullPointerException();
+
+ Node n = head;
+ int i = -1;
+
+ while (n.next != null) {
+ i++;
+ n = n.next;
+ if (n.data.equals(item))
+ return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the index of the last occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int lastIndexOf(ItemType item) {
+
+ if (item == null)
+ throw new NullPointerException();
+
+ Node n = getLastElement();
+ int index = size - 1;
+
+ while (true) {
+
+ if (n.data.equals(item))
+ return index;
+
+ if (n.previous != null) {
+ n = n.previous;
+ //System.out.println("cycling through last-index, looking for " + item + ", have " + n.data);
+ --index;
+ } else {
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns a list iterator over the elements in this list
+ * (in proper sequence).
+ *
+ * @return a list iterator over the elements in this list
+ * (in proper sequence)
+ */
+ @Override
+ public ListIterator listIterator() {
+ return new OurListIterator<>();
+ }
+}
diff --git a/src/edu/greenriver/sdev333/SinglyLinkedList.java b/src/edu/greenriver/sdev333/SinglyLinkedList.java
new file mode 100644
index 0000000..c84d31a
--- /dev/null
+++ b/src/edu/greenriver/sdev333/SinglyLinkedList.java
@@ -0,0 +1,332 @@
+package edu.greenriver.sdev333;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * NOT TESTED - SEE DoublyLinkedList
+ * This class implements the List interface using a SinglyLinkedList.
+ * The code here is not complete, I finished implementing this
+ * interface using a DoublyLinkedList instead.
+ *
+ * @author Paul Woods
+ * @param
+ */
+
+public class SinglyLinkedList implements List {
+
+ // FIELDS - what does a linked list actually have in it??
+ private Node head;
+ private Node tail;
+ private int size;
+
+ // helper/inner class
+ private class Node {
+ ItemType data;
+ Node next;
+ }
+
+ /**
+ * Constructor
+ */
+ public SinglyLinkedList() {
+ // an empty list has no nodes,
+ // which means it has no head
+ head = null;
+ size = 0;
+ }
+
+
+
+ /*
+ * Return a pointer to the last element in the linked-list
+ */
+ private SinglyLinkedList.Node getLastElement() {
+ if (size == 0) {
+ return null;
+ } else {
+ SinglyLinkedList.Node n = head;
+ while (n.next != null) {
+ n = n.next;
+ }
+ return n;
+ }
+ }
+
+
+ /*
+ * Return element at index n
+ */
+ private SinglyLinkedList.Node getElementN(int index) {
+
+ //System.out.print("Retrieving element " + index + ", ");
+
+ if ((index >= size) || (index < 0))
+ throw new IndexOutOfBoundsException();
+
+ SinglyLinkedList.Node n = head;
+ int i = -1;
+
+ while (n.next != null) {
+ i++;
+ n = n.next;
+ if (i == index) {
+ //System.out.println("data, " + n.data);
+ return n;
+ }
+ }
+
+ // we shouldn't be here ...
+ throw new NullPointerException();
+ }
+
+ /**
+ * Returns the number of items in this collection.
+ *
+ * @return the number of items in this collection
+ */
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns true if this collection contains no items.
+ *
+ * @return true if this collection contains no items
+ */
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Returns true if this collection contains the specified item.
+ *
+ * @param item items whose presence in this collection is to be tested
+ * @return true if this collection contains the specified item
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public boolean contains(ItemType item) {
+ return false;
+ }
+
+ /**
+ * Returns an iterator over the elements in this collection.
+ *
+ * @return an Iterator over the elements in this collection
+ */
+ @Override
+ public Iterator iterator() {
+ return null;
+ }
+
+ /**
+ * Adds the specified item to the collection.
+ *
+ * @param item item to be added to the collection
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void add(ItemType item) {
+
+ if (head == null) {
+ head = new SinglyLinkedList.Node();
+ head.next = new SinglyLinkedList.Node();
+ head.next.data = item;
+ } else {
+ SinglyLinkedList.Node currentLast = getLastElement();
+
+ currentLast.next = new SinglyLinkedList.Node();
+ currentLast.next.data = item;
+ }
+
+ ++size;
+ }
+
+ /**
+ * Removes a single instance of the specified item from this collection,
+ * if it is present.
+ *
+ * @param item item to be removed from this collection, if present
+ * @throws NullPointerException if the specified item is null
+ * and this collection does not permit null items
+ */
+ @Override
+ public void remove(ItemType item) {
+
+ }
+
+ /**
+ * Removes all items from this collection.
+ * The collection will be empty after this method returns.
+ */
+ @Override
+ public void clear() {
+ head = null;
+ size = 0;
+ }
+
+ /**
+ * Returns true if this collection contains all the items
+ * in the specified other collection.
+ *
+ * @param otherCollection collection to be checked for containment in this collection
+ * @return true if this collection contains all the items
+ * in the specified other collection
+ */
+ @Override
+ public boolean containsAll(Collection extends ItemType> otherCollection) {
+ return false;
+ }
+
+ /**
+ * Adds all the items in this specified other collection to this collection.
+ *
+ * @param otherCollection collection containing items to be added to this collection
+ */
+ @Override
+ public void addAll(Collection extends ItemType> otherCollection) {
+
+ }
+
+ /**
+ * Removes all of this collection's items that are also contained in the
+ * specified other collection. After this call returns, this collection will
+ * contain no elements in common with the specified other collection.
+ *
+ * @param otherCollection collection containing elements to be removed
+ * from this collection
+ */
+ @Override
+ public void removeAll(Collection extends ItemType> otherCollection) {
+
+ }
+
+ /**
+ * Retains only the items in this collection that are contained in the
+ * specified other collection. In other words, removes from this collection
+ * all of its items that are not contained in the specified other collection
+ *
+ * @param otherCollection collection containing elements to be retained in
+ * this collection
+ */
+ @Override
+ public void retainAll(Collection extends ItemType> otherCollection) {
+
+ }
+
+ /**
+ * Returns the item at the specified position in this list
+ *
+ * @param index index of the item to return
+ * @return the item at the specified position in this list
+ * @throws IndexOutOfBoundsException if this index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public ItemType get(int index) {
+ return null;
+ }
+
+ /**
+ * Replaces the item at the specified position in this list
+ * with the specified item
+ *
+ * @param index index of the item to replace
+ * @param item item to be stored at the specified position
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void set(int index, ItemType item) {
+
+ }
+
+ /**
+ * Inserts the specified item at the specified position in this list.
+ * Shifts the item currently at that position (if any) and any subsequent
+ * items to the right.
+ *
+ * @param index index at which the specified item is to be inserted
+ * @param item item to be inserted
+ * @throws NullPointerException if the specified item is null
+ * and this list does not permit null elements
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void add(int index, ItemType item) {
+ if (item == null)
+ throw new NullPointerException();
+//
+// DoublyLinkedList.Node i = getElementN(index);
+// DoublyLinkedList.Node n = new DoublyLinkedList.Node();
+// n.data = item;
+// n.previous = i.previous; // previous value for new node
+// n.next = i; // next value for new node
+// i.previous.next = n; // next value for old prior node
+// i.previous = n; // previous value for old node
+// ++size;
+ }
+
+ /**
+ * Removes the element at the specified position in this list.
+ * Shifts any subsequent items to the left.
+ *
+ * @param index the index of the item to be removed
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public void remove(int index) {
+
+ }
+
+ /**
+ * Returns the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int indexOf(ItemType item) {
+ return 0;
+ }
+
+ /**
+ * Returns the index of the last occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item.
+ *
+ * @param item the item to search for
+ * @return the index of the first occurrence of the specified item
+ * in this list, or -1 if this list does not contain the item
+ * @throws NullPointerException if the specified item is null and this
+ * list does not permit null items
+ */
+ @Override
+ public int lastIndexOf(ItemType item) {
+ return 0;
+ }
+
+ /**
+ * Returns a list iterator over the elements in this list
+ * (in proper sequence).
+ *
+ * @return a list iterator over the elements in this list
+ * (in proper sequence)
+ */
+ @Override
+ public ListIterator listIterator() {
+ return null;
+ }
+}