diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ 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/ImplementingLists.iml b/ImplementingLists.iml
index c90834f..9c8bf10 100644
--- a/ImplementingLists.iml
+++ b/ImplementingLists.iml
@@ -4,8 +4,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
index 3e59c38..4a721f4 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,5 +1,51 @@
+import edu.greenriver.sdev333.ArrayList;
+import edu.greenriver.sdev333.DoublyLinkedList;
+import edu.greenriver.sdev333.List;
+
+import java.util.Iterator;
+
public class Main {
public static void main(String[] args) {
+
System.out.println("Hello world!");
+
+ List friends = new ArrayList();
+// System.out.println("Initial size is: "+friends.size());
+// System.out.println("List is empty: " + friends.isEmpty());
+//
+// friends.add("Ehren");
+// System.out.println("Size after added one: "+friends.size());
+
+ for(int i = 0; i < 50; i++){
+ friends.add("Friend"+i);
+ }
+// System.out.println("Size after many added: "+friends.size());
+
+// System.out.println(friends.contains("Friend1"));
+// System.out.println(friends.contains("Friendx"));
+
+
+ System.out.println(friends);
+
+// System.out.print(System.lineSeparator());
+// Iterator itr = friends.iterator();
+// while(itr.hasNext()){
+// String name = itr.next();
+// System.out.print(name+" ");
+// }
+//
+// System.out.print(System.lineSeparator());
+// for(String name : friends){
+// System.out.print(name+ " ");
+// }
+
+ List friendsLL = new DoublyLinkedList<>();
+
+ for(int i = 0; i < 50; i++){
+ friendsLL.add("Friend"+i);
+ }
+
+ System.out.println(friendsLL);
+
}
}
\ 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..97c700d
--- /dev/null
+++ b/src/edu/greenriver/sdev333/ArrayList.java
@@ -0,0 +1,586 @@
+package edu.greenriver.sdev333;
+
+import java.util.*;
+
+public class ArrayList implements List{
+
+ // one plain old java array
+ private ItemType[] data;
+
+ // one int to keep track of size
+ // size is the spots that are used in the data array
+ // size is different than lenth of the array
+ private int size;
+
+ //Constructor
+ public ArrayList() {
+ this.data = (ItemType[]) new Object[10];
+ this.size = 0;
+ }
+
+ //Constructor
+ public ArrayList(int capacity) {
+ this.data = (ItemType[]) new Object[capacity];
+ this.size = 0;
+ }
+
+
+ /** returns hashcode for this object by hashing toString with Objects.hash
+ *
+ * @return int hashcode
+ */
+ @Override
+ public int hashCode(){
+ return Objects.hash(this.toString());
+ }
+
+ @Override
+ public boolean equals(Object other){
+ return (other instanceof ArrayList>) && ((ArrayList>) other).hashCode() == hashCode();
+ }
+
+
+ private void trimArray(){
+ ItemType[] tempArray = (ItemType[]) new Object[size];
+ for(int i = 0; i < size; i++){
+ tempArray[i] = data[i];
+ }
+ data = tempArray;
+ }
+
+ /**
+ * 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) {
+ int index = indexOf(item);
+ return isValidIndex(index);
+ }
+
+ /**
+ * Returns an iterator over the elements in this collection.
+ *
+ * @return an Iterator over the elements in this collection
+ */
+ @Override
+ public Iterator iterator() {
+ return new MyCustomIterator();
+ }
+
+
+ /**
+ * 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(!hasRoom()){
+ expand();
+ }
+ data[size] = item;
+ size++;
+
+ }
+
+ private boolean hasRoom(){
+ return size != data.length;
+ }
+
+ private void expand(){
+ //resize up : double array size
+ ItemType[] temp = (ItemType[]) new Object[size * 2];
+ for(int i=0; i < this.size; i++){
+ temp[i] = this.data[i];
+ }
+ this.data = temp;
+ }
+
+ private boolean isValidIndex(int index){
+ return index >= 0 && index < size && size !=0;
+ }
+
+ /**
+ * 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) {
+ int tempSize = 0;
+ ItemType[] tempData = (ItemType[]) new Object[size];
+ for(int i =0; i < size; i++){
+ if(!item.equals(data[i])){
+ tempData[tempSize] = data[i];
+ tempSize++;
+ }
+ }
+ data = tempData;
+ size = tempSize;
+ }
+
+ /**
+ * Removes all items from this collection.
+ * The collection will be empty after this method returns.
+ */
+
+ @Override
+ public String toString(){
+ String output = "[";
+ for(int i=0; i < size-1; i++){
+ output = output + data[i].toString() +", ";
+ }
+ output = output + data[size-1].toString() +"]";
+ return output;
+ }
+ @Override
+ public void clear() {
+ this.data = (ItemType[]) new Object[10];
+ this.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) {
+ //fail fast (fail loud)
+ //throw new UnsupportedOperationException("containsAll method is not supported in this implementation");
+
+ Iterator itr = (Iterator)otherCollection.iterator();
+ while(itr.hasNext()){
+ ItemType itemToCheck = itr.next();
+ if(!contains(itemToCheck)){
+ 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) {
+ //fail fast (fail loud)
+ //throw new UnsupportedOperationException("addAll method is not supported in this implementation");
+ for(ItemType other : otherCollection){
+ add(other);
+ }
+ }
+
+ /**
+ * 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) {
+ //fail fast (fail loud)
+ throw new UnsupportedOperationException("addAll method is not supported in this implementation");
+ }
+
+ /**
+ * 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) {
+ //fail fast (fail loud)
+ throw new UnsupportedOperationException("addAll method is not supported in this implementation");
+ }
+
+ /**
+ * 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(!isValidIndex(index)){
+ throw new IndexOutOfBoundsException("index is out of bounds");
+ }
+ return data[index];
+ }
+
+ /**
+ * 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(!isValidIndex(index)){
+ throw new IndexOutOfBoundsException("index is out of bounds");
+ }
+ data[index] = 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(index > size || index < 0){
+ throw new IndexOutOfBoundsException("index is out of bounds");
+ }
+ if(!hasRoom()){expand();}
+ for(int i = size; i>index; i--){
+ data[i] = data[i-1];
+ }
+ data[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
+ * @return
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= size())
+ */
+ @Override
+ public ItemType remove(int index) {
+ if(!isValidIndex(index)){throw new IndexOutOfBoundsException("Index out of bounds");}
+ //shift values left to overwrite the item at index
+ for(int i = index; i= 0; i--){
+ if(item.equals(data[i])){
+ 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 MyCustomListIterator();
+ }
+
+ private class MyCustomIterator implements Iterator{
+
+ private int currentPosition;
+ public MyCustomIterator(){
+ currentPosition = 0;
+ }
+ /**
+ * Returns {@code true} if the iteration has more elements.
+ * (In other words, returns {@code true} if {@link #next} would
+ * return an element rather than throwing an exception.)
+ *
+ * @return {@code true} if the iteration has more elements
+ */
+ @Override
+ public boolean hasNext() {
+ return currentPosition < size();
+ }
+
+ /**
+ * Returns the next element in the iteration.
+ *
+ * @return the next element in the iteration
+ * @throws NoSuchElementException if the iteration has no more elements
+ */
+ @Override
+ public ItemType next() {
+ return get(currentPosition++);
+ }
+ }
+
+ private class MyCustomListIterator implements ListIterator{
+ private int currentPosition;
+ private int lastIndex;
+ public MyCustomListIterator(){
+ currentPosition = 0;
+ lastIndex = -1;
+ }
+
+ /**
+ * Returns {@code true} if this list iterator has more elements when
+ * traversing the list in the forward direction. (In other words,
+ * returns {@code true} if {@link #next} would return an element rather
+ * than throwing an exception.)
+ *
+ * @return {@code true} if the list iterator has more elements when
+ * traversing the list in the forward direction
+ */
+ @Override
+ public boolean hasNext() {
+ return currentPosition < size();
+ }
+
+ /**
+ * Returns the next element in the list and advances the cursor position.
+ * This method may be called repeatedly to iterate through the list,
+ * or intermixed with calls to {@link #previous} to go back and forth.
+ * (Note that alternating calls to {@code next} and {@code previous}
+ * will return the same element repeatedly.)
+ *
+ * @return the next element in the list
+ * @throws NoSuchElementException if the iteration has no next element
+ */
+ @Override
+ public ItemType next() {
+ lastIndex = currentPosition;
+ return get(currentPosition++);
+ }
+
+ /**
+ * Returns {@code true} if this list iterator has more elements when
+ * traversing the list in the reverse direction. (In other words,
+ * returns {@code true} if {@link #previous} would return an element
+ * rather than throwing an exception.)
+ *
+ * @return {@code true} if the list iterator has more elements when
+ * traversing the list in the reverse direction
+ */
+ @Override
+ public boolean hasPrevious() {
+ return currentPosition > 0;
+ }
+
+ /**
+ * Returns the previous element in the list and moves the cursor
+ * position backwards. This method may be called repeatedly to
+ * iterate through the list backwards, or intermixed with calls to
+ * {@link #next} to go back and forth. (Note that alternating calls
+ * to {@code next} and {@code previous} will return the same
+ * element repeatedly.)
+ *
+ * @return the previous element in the list
+ * @throws NoSuchElementException if the iteration has no previous
+ * element
+ */
+ @Override
+ public ItemType previous() {
+ if(currentPosition - 1 < 0){
+ throw new NoSuchElementException("You are at the beginning of the list");
+ }
+ lastIndex = currentPosition - 1;
+ ItemType returnThis = get(currentPosition -1);
+ currentPosition--;
+ return returnThis;
+ }
+
+ /**
+ * Returns the index of the element that would be returned by a
+ * subsequent call to {@link #next}. (Returns list size if the list
+ * iterator is at the end of the list.)
+ *
+ * @return the index of the element that would be returned by a
+ * subsequent call to {@code next}, or list size if the list
+ * iterator is at the end of the list
+ */
+ @Override
+ public int nextIndex() {
+ return currentPosition;
+ }
+
+ /**
+ * Returns the index of the element that would be returned by a
+ * subsequent call to {@link #previous}. (Returns -1 if the list
+ * iterator is at the beginning of the list.)
+ *
+ * @return the index of the element that would be returned by a
+ * subsequent call to {@code previous}, or -1 if the list
+ * iterator is at the beginning of the list
+ */
+ @Override
+ public int previousIndex() {
+ return currentPosition - 1;
+ }
+
+ /**
+ * Removes from the list the last element that was returned by {@link
+ * #next} or {@link #previous} (optional operation). This call can
+ * only be made once per call to {@code next} or {@code previous}.
+ * It can be made only if {@link #add} has not been
+ * called after the last call to {@code next} or {@code previous}.
+ *
+ * @throws UnsupportedOperationException if the {@code remove}
+ * operation is not supported by this list iterator
+ * @throws IllegalStateException if neither {@code next} nor
+ * {@code previous} have been called, or {@code remove} or
+ * {@code add} have been called after the last call to
+ * {@code next} or {@code previous}
+ */
+ @Override
+ public void remove() {
+ if(lastIndex == -1){
+ throw new IllegalStateException("You can only call remove() once after next() or previous() and not after add()");
+ }
+ for(int i = lastIndex; ilastIndex; i--){
+ data[i] = data[i-1];
+ }
+ data[lastIndex] = item;
+ lastIndex = -1;
+ }
+ }
+}
diff --git a/src/edu/greenriver/sdev333/DoublyLinkedList.java b/src/edu/greenriver/sdev333/DoublyLinkedList.java
new file mode 100644
index 0000000..46316a2
--- /dev/null
+++ b/src/edu/greenriver/sdev333/DoublyLinkedList.java
@@ -0,0 +1,479 @@
+package edu.greenriver.sdev333;
+
+import javax.swing.text.html.HTMLDocument;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+
+public class DoublyLinkedList implements List {
+
+
+ private Node head;
+ private Node tail;
+ private int size;
+
+ public DoublyLinkedList(){
+ //an empty list has no nodes
+ //which means it ahs no head, so set head to null
+ this.head = null;
+ this.tail = null;
+ this.size = 0;
+ }
+
+ /** returns hashcode for this object by hashing toString with Objects.hash
+ *
+ * @return int hashcode
+ */
+ @Override
+ public int hashCode(){
+ return Objects.hash(this.toString());
+ }
+
+ @Override
+ public boolean equals(Object other){
+ return (other instanceof DoublyLinkedList>) && ((DoublyLinkedList>) other).hashCode() == hashCode();
+ }
+
+ @Override
+ public String toString(){
+ String output = "[";
+ Iterator itr = this.iterator();
+ for(int i=0; i < size-1; i++){
+ output = output + itr.next().toString() +", ";
+ }
+ output = output + itr.next().toString() +"]";
+ return output;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * @param item items whose presence in this collection is to be tested
+ * @return
+ */
+ @Override
+ public boolean contains(ItemType item) {
+ int index = indexOf(item);
+ return index != -1;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public Iterator iterator() {
+ return new myIterator();
+ }
+
+ /**
+ * @param item item to be added to the collection
+ */
+ @Override
+ public void add(ItemType item) {
+ Node looseNode = new Node(item);
+ if(this.head == null){
+ this.head = looseNode;
+ this.tail = looseNode;
+ this.size++;
+ }else{
+ looseNode.prev = this.tail;
+ this.tail.next = looseNode;
+ this.tail = looseNode;
+ this.size++;
+ }
+ }
+
+ /**
+ * @param item item to be removed from this collection, if present
+ */
+ @Override
+ public void remove(ItemType item) {
+ int index = indexOf(item);
+ if(index != -1){
+ remove(index);
+ }
+ }
+
+ public int remove(ItemType item, boolean returnIndex) {
+ int index = indexOf(item);
+ if(index != -1){
+ remove(index);
+ }
+ return index;
+ }
+
+ public void removeEvery(ItemType item){
+ if(remove(item, true) != -1){
+ removeEvery(item);
+ }
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void clear() {
+ head = null;
+ size = 0;
+ }
+
+ /**
+ * @param otherCollection collection to be checked for containment in this collection
+ * @return
+ */
+ @Override
+ public boolean containsAll(Collection extends ItemType> otherCollection) {
+ throw new UnsupportedOperationException("The containsAll() method is not implemented here.");
+ }
+
+ /**
+ * @param otherCollection collection containing items to be added to this collection
+ */
+ @Override
+ public void addAll(Collection extends ItemType> otherCollection) {
+ for(ItemType other : otherCollection){
+ add(other);
+ }
+ }
+
+ /**
+ * @param otherCollection collection containing elements to be removed
+ * from this collection
+ */
+ @Override
+ public void removeAll(Collection extends ItemType> otherCollection) {
+ for(ItemType other : otherCollection){
+ removeEvery(other);
+ }
+ }
+
+ /**
+ * @param otherCollection collection containing elements to be retained in
+ * this collection
+ */
+ @Override
+ public void retainAll(Collection extends ItemType> otherCollection) {
+ throw new UnsupportedOperationException("The retailAll() method is not implemented here.");
+ }
+
+ /**
+ * @param i index of the item to return
+ * @return
+ */
+ @Override
+ public ItemType get(int i) {
+ if(i < 0 || i >= this.size) throw new IndexOutOfBoundsException("Index out of bounds in call to get(int).");
+ Node current = this.head;
+ for(int j = 0; j < i; j++){
+ current = current.next;
+ }
+ return current.data;
+ }
+
+ /**
+ * @param i index of the item to replace
+ * @param item item to be stored at the specified position
+ */
+ @Override
+ public void set(int i, ItemType item) {
+ if(i < 0 || i >= this.size) throw new IndexOutOfBoundsException("Index out of bounds in call to get(int).");
+ Node current = this.head;
+ for(int j = 0; j < i; j++){
+ current = current.next;
+ }
+ current.data = item;
+ }
+
+ /**
+ * @param index index at which the specified item is to be inserted
+ * @param item item to be inserted
+ */
+ @Override
+ public void add(int index, ItemType item) {
+ if(index < 0 || index > this.size) throw new IndexOutOfBoundsException("IndexOutOfBounds in call to add(int, ItemType)");
+ Node looseNode = new Node(item);
+ if(this.head == null){
+ this.head = looseNode;
+ this.tail = looseNode;
+ this.size = 1;
+ }else if(index == 0){
+ looseNode.next = this.head;
+ this.head = looseNode;
+ this.size++;
+ }else if(index == this.size){
+ this.add(item);
+ }else{
+ Node current = this.head;
+ for(int i = 0; i < index - 1; i++){
+ current = current.next;
+ }
+ current.next.prev = looseNode;
+ looseNode.next = current.next;
+ looseNode.prev = current;
+ current.next = looseNode;
+ this.size++;
+ }
+ }
+
+ /** This method removes the last element from the list, and returns it.
+ *
+ * @return The object removed from the list.
+ * @throws IndexOutOfBoundsException if the list is empty.
+ */
+ public ItemType remove() throws IndexOutOfBoundsException {
+ if(this.size == 0)throw new IndexOutOfBoundsException("The list is empty, but you called remove().");
+ if(this.size == 1){
+ Node lastOne = this.head;
+ this.head = null;
+ this.tail = null;
+ this.size = 0;
+ return lastOne.data;
+ }else{
+ Node end = this.tail;
+ this.tail = this.tail.prev; //There is no previous, if this was the only node
+ this.tail.next = null;
+ //end.prev = null; //does not matter what it points at, there is nothing pointing at it, right? (for garbage collection)
+ this.size--;
+ return end.data;
+ }//end if else
+ }//end remove
+
+ /**
+ * @param index the index of the item to be removed
+ * @return
+ */
+ @Override
+ public ItemType remove(int index) {
+ if(index < 0 || index >= this.size) throw new IndexOutOfBoundsException("Index out of bounds in call to remove(int).");
+ if(index == this.size - 1){
+ return this.remove();
+ }else if(index == 0){
+ Node start = this.head;
+ this.head = this.head.next;
+ this.head.prev = null;
+ this.size--;
+ return start.data;
+ }else{
+ Node current = this.head;
+ for(int i = 0; i < index; i++){
+ current = current.next;
+ }
+ current.prev.next = current.next;
+ current.next.prev = current.prev;
+ this.size--;
+ return current.data;
+ }//end if else
+ }
+
+ /**
+ * @param item the item to search for
+ * @return
+ */
+ @Override
+ public int indexOf(ItemType item) {
+ Node current = this.head;
+ for(int i = 0; i < this.size; i++){
+ if(current.data.equals(item))return i;
+ current = current.next;
+ }
+ return -1;
+ }
+
+ /**
+ * @param item the item to search for
+ * @return
+ */
+ @Override
+ public int lastIndexOf(ItemType item) {
+ Node current = this.tail;
+ for(int i = this.size - 1; i >= 0; i--){
+ if(current.data.equals(item))return i;
+ current = current.prev;
+ }
+ return -1;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public ListIterator listIterator() {
+ return new myListIterator();
+ }
+
+
+
+ //**************** Private Subclass Node *************************************
+ private class Node {
+ public ItemType data;
+ public Node next;
+ public Node prev;
+
+ public Node(ItemType d){
+ this.data = d;
+ this.next = null;
+ this.prev = null;
+ }
+ }
+
+ private class myIterator implements Iterator {
+ private Node currentNode;
+ private int currentPosition;
+ public myIterator(){
+ currentNode = head;
+ currentPosition = 0;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public boolean hasNext() {
+ return currentNode != null;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public ItemType next() {
+ ItemType data = currentNode.data;
+ currentNode = currentNode.next;
+ currentPosition++;
+ return data;
+ }
+
+ }
+
+ private class myListIterator implements ListIterator{
+
+ private Node currentNode;
+ private int currentPosition;
+ private int lastIndex;
+
+ public myListIterator(){
+ currentNode = head;
+ currentPosition = 0;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public boolean hasNext() {
+ return currentNode != null;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public ItemType next() {
+ if(!hasNext()){throw new NoSuchElementException("You should check hasNext() before calling next()");}
+ ItemType data = currentNode.data;
+ currentNode = currentNode.next;
+ lastIndex = currentPosition;
+ currentPosition++;
+ return data;
+ }
+
+ public boolean hasPrevious(){
+ return currentPosition != 0;
+ }
+
+ public ItemType previous(){
+ if(!hasPrevious()){
+ throw new NoSuchElementException("Node at beginning of list has no previous. Check hasPrevious() before calling previous()");
+ }
+ if(currentPosition == size){
+ currentNode = tail;
+ currentPosition--;
+ lastIndex = currentPosition;
+ return currentNode.data;
+ } else{
+ currentNode = currentNode.prev;
+ currentPosition--;
+ lastIndex = currentPosition;
+ return currentNode.data;
+ }
+ }
+
+ /** The index-position of the element that you will get when you call next()
+ * @return
+ */
+ @Override
+ public int nextIndex() {
+ return currentPosition;
+ }
+
+ /**
+ * @return
+ */
+ @Override
+ public int previousIndex() {
+ return currentPosition - 1;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void remove() {
+ if(lastIndex == currentPosition) {
+ int remove = lastIndex;
+ ItemType ignoreThis = previous();
+ DoublyLinkedList.this.remove(remove);
+ }else if(lastIndex == size - 1){
+ int remove = lastIndex;
+ ItemType ignoreThis = previous();
+ //ItemType ignoreThisToo = previous();
+ DoublyLinkedList.this.remove(remove);
+ }else{
+ DoublyLinkedList.this.remove(lastIndex);
+ }
+ }
+
+ /**
+ * @param item the element with which to replace the last element returned by
+ * {@code next} or {@code previous}
+ */
+ @Override
+ public void set(ItemType item) {
+ DoublyLinkedList.this.set(lastIndex, item);
+ }
+
+ /**
+ * @param item the element to insert
+ */
+ @Override
+ public void add(ItemType item) {
+ if(lastIndex == size - 1) {
+ DoublyLinkedList.this.add(item);
+ currentNode = tail.next;
+ currentPosition = size;
+ }else if(size == 0){
+ DoublyLinkedList.this.add(item);
+ currentNode = head;
+ currentPosition = 0;
+ }else{
+ DoublyLinkedList.this.add(lastIndex, item);
+ }
+ }
+ }
+
+}
diff --git a/src/edu/greenriver/sdev333/List.java b/src/edu/greenriver/sdev333/List.java
index 792abd2..c57aec2 100644
--- a/src/edu/greenriver/sdev333/List.java
+++ b/src/edu/greenriver/sdev333/List.java
@@ -106,10 +106,11 @@ public interface List extends Collection {
* Shifts any subsequent items to the left.
*
* @param index the index of the item to be removed
+ * @return
* @throws IndexOutOfBoundsException if the index is out of range
- * (index < 0 || index >= size())
+ * (index < 0 || index >= size())
*/
- void remove(int index);
+ ItemType remove(int index);
/**
* Returns the index of the first occurrence of the specified item
diff --git a/tests/edu/greenriver/sdev333/ArrayListTest.java b/tests/edu/greenriver/sdev333/ArrayListTest.java
new file mode 100644
index 0000000..28d9d60
--- /dev/null
+++ b/tests/edu/greenriver/sdev333/ArrayListTest.java
@@ -0,0 +1,205 @@
+package edu.greenriver.sdev333;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ArrayListTest {
+
+ ArrayList testListOne = new ArrayList<>(5);
+ ArrayList testListTwo = new ArrayList<>(2);
+
+ @org.junit.jupiter.api.Test
+ void testEquals() {
+ testListOne.add("foo");
+ testListTwo.add("foo");
+ assertEquals(true, testListOne.equals(testListTwo));
+ testListOne.add("bar");
+ assertEquals(false, testListOne.equals(testListTwo));
+ }
+
+ @org.junit.jupiter.api.Test
+ void size() {
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals(2, testListOne.size());
+ }
+
+ @org.junit.jupiter.api.Test
+ void isEmpty() {
+ assertEquals(true, testListOne.isEmpty());
+ testListOne.add("one");
+ assertEquals(false, testListOne.isEmpty());
+ }
+
+ @org.junit.jupiter.api.Test
+ void contains() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals(true, testListOne.contains("foo"));
+ assertEquals(false, testListOne.contains("nope"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void iterator() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ Iterator itr = testListOne.iterator();
+ assertEquals(true, itr instanceof Iterator);
+ assertEquals("one", itr.next());
+ assertEquals("bar", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("foo", itr.next());
+ assertEquals(false, itr.hasNext());
+ }
+
+ @org.junit.jupiter.api.Test
+ void add() {
+ //trivial : included with other tests
+ }
+
+ @org.junit.jupiter.api.Test
+ void remove() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.remove(1);
+ assertEquals("foo", testListOne.get(1));
+ }
+
+ @org.junit.jupiter.api.Test
+ void testToString() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("[one, bar, foo]", testListOne.toString());
+ }
+
+ @org.junit.jupiter.api.Test
+ void clear() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.clear();
+ assertEquals(true, testListOne.isEmpty());
+ assertEquals(0, testListOne.size());
+ }
+
+ @org.junit.jupiter.api.Test
+ void containsAll() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("more");
+ testListOne.add("stuff");
+ testListOne.add("now");
+
+ testListTwo.add("bar");
+ testListTwo.add("foo");
+
+ assertEquals(true, testListOne.containsAll(testListTwo));
+
+ testListTwo.add("nope");
+ assertEquals(false, testListOne.containsAll(testListTwo));
+
+ }
+
+ @org.junit.jupiter.api.Test
+ void addAll() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+
+ testListTwo.add("more");
+ testListTwo.add("stuff");
+
+ testListOne.addAll(testListTwo);
+ assertEquals("[one, bar, foo, more, stuff]", testListOne.toString());
+ }
+
+ @org.junit.jupiter.api.Test
+ void get() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("foo", testListOne.get(2));
+ }
+
+ @org.junit.jupiter.api.Test
+ void set() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("foo", testListOne.get(2));
+ testListOne.set(2, "new");
+ assertEquals("new", testListOne.get(2));
+ }
+
+ @org.junit.jupiter.api.Test
+ void indexOf() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ assertEquals(3, testListOne.indexOf("new"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void lastIndexOf() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ assertEquals(2, testListOne.indexOf("foo"));
+ assertEquals(6, testListOne.lastIndexOf("foo"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void listIterator() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("more");
+ testListOne.add("stuff");
+
+ ListIterator itr = testListOne.listIterator();
+ assertEquals("one", itr.next());
+ assertEquals("bar", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("foo", itr.next());
+ assertEquals("foo", itr.previous());
+ assertEquals("bar", itr.previous());
+ assertEquals(true, itr.hasPrevious());
+ assertEquals("one", itr.previous());
+ assertEquals(false, itr.hasPrevious());
+ assertEquals("one", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("bar", itr.next());
+ assertEquals("foo", itr.next());
+ assertEquals("more", itr.next());
+ assertEquals("stuff", itr.next());
+ assertEquals(false, itr.hasNext());
+ assertEquals("stuff", itr.previous());
+ assertEquals(4, itr.nextIndex());
+ assertEquals(3, itr.previousIndex());
+ assertEquals("stuff", itr.next());
+ itr.remove();
+ assertEquals("more", itr.previous());
+ itr.set("less");
+ assertEquals("less", itr.next());
+ assertEquals(false, itr.hasNext());
+ itr.add("time");
+ assertEquals(false, itr.hasNext());
+ assertEquals("time", itr.previous());
+ assertEquals("foo", itr.previous());
+
+
+ }
+}
\ No newline at end of file
diff --git a/tests/edu/greenriver/sdev333/DoublyLinkedListTest.java b/tests/edu/greenriver/sdev333/DoublyLinkedListTest.java
new file mode 100644
index 0000000..ca2c91c
--- /dev/null
+++ b/tests/edu/greenriver/sdev333/DoublyLinkedListTest.java
@@ -0,0 +1,197 @@
+package edu.greenriver.sdev333;
+//tests passing
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class DoublyLinkedListTest {
+
+ DoublyLinkedList testListOne = new DoublyLinkedList<>();
+ DoublyLinkedList testListTwo = new DoublyLinkedList<>();
+
+ @org.junit.jupiter.api.Test
+ void testEquals() {
+ testListOne.add("foo");
+ testListTwo.add("foo");
+ assertEquals(true, testListOne.equals(testListTwo));
+ testListOne.add("bar");
+ assertEquals(false, testListOne.equals(testListTwo));
+ }
+
+ @org.junit.jupiter.api.Test
+ void size() {
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals(2, testListOne.size());
+ }
+
+ @org.junit.jupiter.api.Test
+ void isEmpty() {
+ assertEquals(true, testListOne.isEmpty());
+ testListOne.add("one");
+ assertEquals(false, testListOne.isEmpty());
+ }
+
+ @org.junit.jupiter.api.Test
+ void contains() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals(true, testListOne.contains("foo"));
+ assertEquals(false, testListOne.contains("nope"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void iterator() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ Iterator itr = testListOne.iterator();
+ assertEquals(true, itr instanceof Iterator);
+ assertEquals("one", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("bar", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("foo", itr.next());
+ //assertEquals(false, itr.hasNext());
+ }
+
+ @org.junit.jupiter.api.Test
+ void add() {
+ //trivial : included with other tests
+ }
+
+ @org.junit.jupiter.api.Test
+ void remove() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.remove(1);
+ assertEquals("foo", testListOne.get(1));
+ }
+
+ @org.junit.jupiter.api.Test
+ void testToString() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("[one, bar, foo]", testListOne.toString());
+ }
+
+ @org.junit.jupiter.api.Test
+ void clear() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.clear();
+ assertEquals(true, testListOne.isEmpty());
+ assertEquals(0, testListOne.size());
+ }
+
+ @org.junit.jupiter.api.Test
+ void addAll() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+
+ testListTwo.add("more");
+ testListTwo.add("stuff");
+
+ testListOne.addAll(testListTwo);
+ assertEquals("[one, bar, foo, more, stuff]", testListOne.toString());
+ }
+
+ @org.junit.jupiter.api.Test
+ void get() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("foo", testListOne.get(2));
+ }
+
+ @org.junit.jupiter.api.Test
+ void set() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ assertEquals("foo", testListOne.get(2));
+ testListOne.set(2, "new");
+ assertEquals("new", testListOne.get(2));
+ }
+
+ @org.junit.jupiter.api.Test
+ void indexOf() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ assertEquals(3, testListOne.indexOf("new"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void lastIndexOf() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("new");
+ assertEquals(2, testListOne.indexOf("foo"));
+ assertEquals(6, testListOne.lastIndexOf("foo"));
+ }
+
+ @org.junit.jupiter.api.Test
+ void listIterator() {
+ testListOne.add("one");
+ testListOne.add("bar");
+ testListOne.add("foo");
+ testListOne.add("more");
+ testListOne.add("stuff");
+
+ ListIterator itr = testListOne.listIterator();
+ assertEquals(0, itr.nextIndex());
+ assertEquals("one", itr.next());
+ assertEquals("bar", itr.next());
+ assertEquals(2, itr.nextIndex());
+ assertEquals(true, itr.hasNext());
+ assertEquals("foo", itr.next());
+ assertEquals(3, itr.nextIndex());
+ assertEquals(2, itr.previousIndex());
+ assertEquals("foo", itr.previous());
+ assertEquals(2, itr.nextIndex());
+ assertEquals("foo", itr.next());
+ assertEquals("foo", itr.previous());
+ assertEquals("bar", itr.previous());
+ assertEquals(true, itr.hasPrevious());
+ assertEquals("one", itr.previous());
+ assertEquals(false, itr.hasPrevious());
+ assertEquals("one", itr.next());
+ assertEquals(true, itr.hasNext());
+ assertEquals("bar", itr.next());
+ assertEquals("foo", itr.next());
+ assertEquals("more", itr.next());
+ assertEquals("stuff", itr.next());
+ assertEquals(false, itr.hasNext());
+ assertEquals("stuff", itr.previous());
+ assertEquals(4, itr.nextIndex());
+ assertEquals(3, itr.previousIndex());
+ assertEquals("stuff", itr.next());
+ itr.remove();
+ assertEquals("more", itr.previous());
+ itr.set("less");
+ assertEquals("less", itr.next());
+ assertEquals(false, itr.hasNext());
+ itr.add("time");
+ assertEquals(false, itr.hasNext());
+ assertEquals("time", itr.previous());
+ assertEquals("less", itr.previous());
+
+
+ }
+}
\ No newline at end of file