diff --git a/.idea/misc.xml b/.idea/misc.xml index 6f29fee..5af9c98 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - 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/SDEV333-Term-Project.iml b/SDEV333-Term-Project.iml index c90834f..9c8bf10 100644 --- a/SDEV333-Term-Project.iml +++ b/SDEV333-Term-Project.iml @@ -4,8 +4,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ArrayList.java b/src/ArrayList.java new file mode 100644 index 0000000..6320fff --- /dev/null +++ b/src/ArrayList.java @@ -0,0 +1,335 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ArrayList implements List { + + private int size; + private E[] buffer; + + public ArrayList() { + buffer = (E[])new Object[10]; + size = 0; + } + + /** + * Add item to the front. + * + * Runtime analysis: Best case is O(1) constant for an empty array, and worse case is O(N) + * for looping through an entire array shifting all values over. + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + if(size == buffer.length) { // 1 + increaseBuffer(); // O(N) 5 + (8 * n) + } + for(int i = size; i > 0; i--) { // 6 * n + buffer[i] = buffer[i - 1]; // + } + buffer[0] = item; // 1 + size++; // 2 + } + + /** + * Add item to the back. + * + * Runtime Analysis: Best case is O(1) for an empty array/ array that's + * not full. Worst case is O(N) linear having to increase the buffer size. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + if(size == buffer.length) { + increaseBuffer(); + } + buffer[size] = item; + size++; + } + + /** + * Add an item at specified index (position). + * + * Runtime Analysis: Best case is O(1) for an empty array, adding a value at index 0. Worst case is + * O(N) for looping through an entire array of N size, or if the length needs to be increased. + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + if(isEmpty()) { + if(i == 0) { + buffer[i] = item; + size++; + } else { + throw new IndexOutOfBoundsException("List is empty."); + } + } else { + if(size == buffer.length) { + increaseBuffer(); + } + for(int j = size + 1; j > i; j--) { + buffer[j] = buffer[j - 1]; + } + buffer[i] = item; + size++; + } + + } + + /** + * Get the item at a specified index. + * + * Runtime Analysis: Worst case is O(1) for an empty array, and returning + * a value at a specified index. + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to return."); + } else if(i > size - 1|| i < 0) { + throw new IndexOutOfBoundsException("List is empty."); + } else { + return buffer[i]; + } + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * + * Runtime Analysis: Best case is O(1) for an empty array, and only having to access + * an index/ change the value. + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + if(isEmpty()) { + if(i == 0) { + buffer[i] = item; + size++; + } else { + throw new NoSuchElementException("List is empty, must set first index."); + } + } else if(i > size - 1 || i < 0) { + throw new IndexOutOfBoundsException(); + } else { + buffer[i] = item; + } + } + + /** + * Remove item at the front of the list. + * + * Runtime Analysis: Best case is O(1) for an empty array, and worst case is + * O(N) for looping through an entire array to shift all values over. + * + * @return the item that was removed + */ + @Override + public E removeFront() { + if(isEmpty()) { + throw new IndexOutOfBoundsException("List is empty."); + } else { + E removedVal = buffer[0]; + for(int i = 0; i < size - 1; i++) { + buffer[i] = buffer[i + 1]; + } + size--; + return removedVal; + } + } + + /** + * Remove item at the back of the list + * + * Runtime Analysis: Best case is O(1) for an empty array, and worst case is + * O(N) for looping through an entire array of N size. + * + * @return the item that was removed + */ + @Override + public E removeBack() { + if(isEmpty()) { + throw new IndexOutOfBoundsException("List is empty."); + } else { + E removedVal = buffer[size - 1]; + buffer[size - 1] = null; + size--; + return removedVal; + } + } + + /** + * Remove item from the list + * + * Runtime Analysis: Best case is O(1) constant for an empty array. Worst case is + * O(N) linear with having to loop through an array then calling the remove method. + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to remove."); + } else { + for(int i = 0; i < size; i++) { + if(buffer[i].equals(item)) { + remove(i); + } + } + size--; + } + } + + /** + * Remove item at a specified index. + * + * Runtime Analysis: Best case is O(1) constant in the case of an empty + * array/invalid index. At its worst it's O(N) linear due to looping through an array + * of N size, and the index potentially being at the end. + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + if(isEmpty() || i > size - 1 || i < 0) { + throw new IndexOutOfBoundsException(); + } else { + E removedVal = buffer[i]; + for(int j = i; j < size - 1; j++) { + buffer[j] = buffer[j + 1]; + } + size--; + return removedVal; + } + } + + /** + * Checks if an item is in the list. + * + * Runtime Analysis: At its best the method runs at O(1) in the case of + * an empty array, and at its worst O(N) Linear due looping through an + * array of N length with the possibility of the desired val being at + * the end. + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + if(isEmpty()) { + return false; + } + for(int i = 0; i < size; i++) { + if(buffer[i].equals(item)) { + return true; + } + } + return false; + } + + /** + * Checks if the list is empty. + * + * Runtime Analysis: O(1) constant, this is the worst + * case scenario because it simply returns the result of + * a comparison. + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Provides a count of the number of items in the list. + * + * Runtime Analysis: Runs at O(1) constant at it's worst + * because it's always just returning a single variable. + * + * @return number of items in the list + */ + @Override + public int size() { + return size; + } + + + /** + * Runtime analysis: At it's worst it's O(N) linear because it has + * to loop through all values an array twice, and the size of the + * array can vary. + */ + + private void increaseBuffer() { + E[] hold = (E[])new Object[buffer.length]; // 2 + for(int i = 0; i < size - 1; i++) { // 4 * n + hold[i] = buffer[i]; + } + + buffer = (E[])new Object[buffer.length * 2]; // 3 + for(int i = 0; i < size - 1; i++) { // 4 * n + buffer[i] = hold[i]; + } + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new ArrayListIterator(); + } + + public class ArrayListIterator implements Iterator { + + private int i; + + private ArrayListIterator() { + i = 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 i < 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 E next() { + if(!hasNext()) { + throw new NoSuchElementException(); + } + E currentVal = buffer[i]; + i++; + return currentVal; + } + } + + + +} diff --git a/src/Bag.java b/src/Bag.java new file mode 100644 index 0000000..c7b844c --- /dev/null +++ b/src/Bag.java @@ -0,0 +1,30 @@ +/** + * Bag API + * + * @param class / datatype of items in the Bag. + */ +public interface Bag extends Iterable { + + /** + * Adds an item to the bag. + * + * @param item the item to be added + */ + void add(E item); + + /** + * Checks if the Bag is empty. + * + * @return true if the bag is empty, otherwise returns false. + */ + boolean isEmpty(); + + /** + * Keeps track of the current number of items stored within + * the bag. Increments and decreases any time a value is + * added/removed. + * + * @return current size of the bag. + */ + int size(); +} diff --git a/src/LinkedList.java b/src/LinkedList.java new file mode 100644 index 0000000..b23a1e8 --- /dev/null +++ b/src/LinkedList.java @@ -0,0 +1,360 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedList implements List { + + private class Node { + E data; + Node next; + } + + private Node head; + private int size; + + public LinkedList() { + head = null; + size = 0; + } + + /** + * Add item to the front. + * + * Runtime Analysis: This method runs at O(1) constant for either an empty list + * or just adding node to the front. + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + Node newNode = new Node(); + newNode.data = item; + newNode.next = head; + head = newNode; + size++; + } + + /** + * Add item to the back. + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list, + * at its worst is O(N) linear having to loop through the entire list with N size. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + Node newNode = new Node(); + newNode.data = item; + if(isEmpty()) { + head = newNode; + } else if(size == 1) { + head.next = newNode; + } else { + int counter = 0; + for(Node current = head; current != null; current = current.next) { + if(counter == size - 1) { + current.next = newNode; + break; + } + counter++; + } + } + size++; + } + + /** + * Add an item at specified index (position). + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list or with + * the index being 0. At its worst is O(N) linear having to loop through the entire list with N size + * to reach the last node. + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + if(i == 0) { + addFront(item); + } else if(isEmpty()) { + throw new IndexOutOfBoundsException("List is empty, value must be added to the front"); + } else if(i > size - 1 || i < 0) { + throw new IndexOutOfBoundsException("Invalid index."); + } + Node newNode = new Node(); + newNode.data = item; + int counter = 0; + for(Node current = head; current.next != null; current = current.next) { + if(counter == i - 1) { + newNode.next = current.next; + current.next = newNode; + size++; + } + counter++; + } + } + + /** + * Get the item at a specified index. + * + * Runtime Analysis: This method runs at O(1) constant at its best for an + * empty list/ desired index being the front. At its worst it runs at + * O(N) if the desired value is at the end of the list. + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to return."); + } else if (i > size - 1 || i < 0) { + throw new IndexOutOfBoundsException("Invalid index."); + } else if(size == 1) { + return head.data; + } + int counter = 0; + E retreivedVal = null; + for(Node current = head; current != null; current = current.next) { + if(counter == i) { + retreivedVal = current.data; + } + counter++; + } + return retreivedVal; + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list + * or desired node to be changed at the front. At its worst is O(N) linear having to loop + * through the entire list with N size to set the last node. + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + if(isEmpty() && i > 0) { + throw new IndexOutOfBoundsException("List is empty, value must be placed at the front"); + } else if(i < 0 || i > size - 1) { + throw new IndexOutOfBoundsException("Invalid index"); + } + int counter = 0; + for(Node current = head; current != null; current = current.next) { + if(counter == i) { + current.data = item; + } + counter++; + } + } + + /** + * Remove item at the front of the list. + * + * Runtime Analysis: This method runs at O(1) constant for an empty list, and for + * removing the first node. + * + * @return the item that was removed + */ + @Override + public E removeFront() { + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to remove."); + } + E removedVal = head.data; + head = head.next; + size--; + return removedVal; + } + + /** + * Remove item at the back of the list + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list, + * or a list of size 1. At its worst is O(N) linear having to loop through the entire + * list with N size. + * + * @return the item that was removed + */ + @Override + public E removeBack() { + E removedVal = null; + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to remove"); + } else if (size == 1) { + removedVal = head.data; + head = null; + return removedVal; + } + for(Node current = head; current != null; current = current.next) { + if(current.next.next == null) { + removedVal = current.next.data; + current.next = null; + size--; + } + } + return removedVal; + } + + /** + * Remove item from the list + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list/ single value + * list. At its worst is O(N) linear having to loop through the entire list with N size to check + * for desired value. + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to remove."); + } else if (size == 1) { + if(head.data.equals(item)) { + head.data = null; + size--; + } + } + for(Node current = head; current.next != null; current = current.next) { + if(current.next.data.equals(item)) { + current.next = current.next.next; + size--; + break; + } + } + } + + /** + * Remove item at a specified index. + * + * Runtime Analysis: At its best this method runs at O(1) constant for an empty list or index + * being 0. At its worst is O(N) linear having to loop through the entire list with N size to + * reach last index. + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + E removedVal = null; + if(isEmpty()) { + throw new NoSuchElementException("List is empty, no values to remove."); + } else if(i > size - 1 || i < 0) { + throw new IndexOutOfBoundsException(); + } else if(size == 1) { + removedVal = head.data; + head.data = null; + size--; + return removedVal; + } + int counter = 0; + + for(Node current = head; current != null; current = current.next) { + if(counter == i - 1) { + removedVal = current.next.data; + current.next = current.next.next; + size--; + break; + } + counter++; + } + return removedVal; + } + + /** + * Checks if an item is in the list. + * + * Runtime Analysis: This method runs at O(N) linear due to + * having to loop through the entire array to check for the + * val. + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + if(isEmpty()) { + return false; + } else if(size == 1) { + return head.data.equals(item); + } + for(Node current = head; current.next != null; current = current.next) { + if(current.data.equals(item)) { + return true; + } + } + return false; + } + + /** + * Checks if the list is empty. + * + * Runtime Analysis: This method runs at O(1) constant always returning + * the result of a check. + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Provides a count of the number of items in the list. + * + * Runtime Analysis: This method runs at O(1) constant always returning size. + * + * @return number of items in the list + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new LinkedListIterator(); + } + + public class LinkedListIterator implements Iterator { + + private Node current; + + private LinkedListIterator() { + current = head; + } + + /** + * 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 current != null; + } + + /** + * 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 E next() { + E val = current.data; + current = current.next; + return val; + } + } +} diff --git a/src/Main.java b/src/Main.java index 8f8f984..7c6b4f7 100644 --- a/src/Main.java +++ b/src/Main.java @@ -6,5 +6,15 @@ public static void main(String[] args) { // to see how IntelliJ IDEA suggests fixing it. System.out.println("Hello and welcome!"); + ArrayList listTest = new ArrayList<>(); + listTest.addFront(21); + listTest.addFront(20); + listTest.addFront(19); + + for(Integer i : listTest) { + System.out.println(i); + } + + } } \ No newline at end of file diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java new file mode 100644 index 0000000..e89a38e --- /dev/null +++ b/src/ResizingArrayStack.java @@ -0,0 +1,117 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ResizingArrayStack implements Stack { + + private E[] buffer; + private int size; + + public ResizingArrayStack() { + buffer = (E[]) new Object[50]; + size = 0; + } + + /** + * Add an item to the stack. + * + * @param item the item to be added + */ + @Override + public void push(E item) { + if(size == buffer.length) { + increaseBuffer(buffer.length * 2); + } + buffer[size] = item; + size++; + } + + /** + * Removes the most recently added item from the stack. + * + * @return the item that was removed + */ + @Override + public E pop() { + E removedItem = buffer[size - 1]; + buffer[size - 1] = null; + size--; + if(size > 0 && size == buffer.length/4) { + increaseBuffer(buffer.length / 2); + } + return removedItem; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * + * @return item at the top of the stack. + */ + @Override + public E peek() { + if(isEmpty()) { + throw new NoSuchElementException("Stack is empty, no value to return"); + } + return buffer[size - 1]; + } + + /** + * Checks to see if the stack is empty. + * + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the stack. + * + * @return the number of items in the stack + */ + @Override + public int size() { + return size; + } + + private void increaseBuffer(int max) { + E[] temp = (E[]) new Object[max]; + for(int i = 0; i < size; i++) { + temp[i] = buffer[i]; + } + buffer = temp; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new ResizingArrayStackIterator(); + } + + private class ResizingArrayStackIterator implements Iterator { + private int i; + + private ResizingArrayStackIterator() { + i = size; + } + + public boolean hasNext() { + return i > 0; + } + + public E next() { + if(!hasNext()) { + throw new NoSuchElementException(); + } + E currentVal = buffer[i]; + i--; + return currentVal; + } + + } +} diff --git a/src/StackTestClient.java b/src/StackTestClient.java new file mode 100644 index 0000000..001789c --- /dev/null +++ b/src/StackTestClient.java @@ -0,0 +1,20 @@ +import java.util.Scanner; + class StackTestClient { + public static void main(String[] args) { + Stack s = new ResizingArrayStack(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while(in.hasNext()) { + String item = in.next(); + + if(item.equals("-")) { + s.push("item"); + } else if(!s.isEmpty()) { + System.out.println(s.pop() + " "); + } + } + + System.out.println("(" + s.size() + ") left on the stack"); + } +} diff --git a/tests/ArrayListTest.java b/tests/ArrayListTest.java new file mode 100644 index 0000000..51ab317 --- /dev/null +++ b/tests/ArrayListTest.java @@ -0,0 +1,125 @@ +import static org.junit.jupiter.api.Assertions.*; + +class ArrayListTest { + + ArrayList emptyList = new ArrayList<>(); + ArrayList singleItemList = fillList(1); + ArrayList multiItemList = fillList(10); + + public ArrayList fillList(int size) { + ArrayList list = new ArrayList<>(); + for(int i = 0; i <= size - 1; i++) { + list.addBack(i + 1); + } + return list; + } + + + @org.junit.jupiter.api.Test + void addFront() { + assertTrue(emptyList.isEmpty()); + emptyList.addFront(30); + assertEquals(30, emptyList.get(0)); + + assertEquals(1, singleItemList.get(0)); + singleItemList.addFront(30); + assertEquals(30, singleItemList.get(0)); + + assertEquals(1, multiItemList.get(0)); + multiItemList.addFront(30); + assertEquals(30, multiItemList.get(0)); + } + + @org.junit.jupiter.api.Test + void addBack() { + assertTrue(emptyList.isEmpty()); + emptyList.addBack(30); + assertEquals(30, emptyList.get(emptyList.size() - 1)); + + assertEquals(1, singleItemList.get(singleItemList.size() - 1)); + singleItemList.addBack(30); + assertEquals(30, singleItemList.get(singleItemList.size() - 1)); + + assertEquals(10, multiItemList.get(multiItemList.size() - 1)); + multiItemList.addBack(30); + assertEquals(30, multiItemList.get(multiItemList.size() - 1)); + } + + @org.junit.jupiter.api.Test + void add() { + assertTrue(emptyList.isEmpty()); + emptyList.add(0,30); + assertEquals(30, emptyList.get(0)); + + assertFalse(singleItemList.contains(21)); + singleItemList.add(0, 21); + assertEquals(21, singleItemList.get(0)); + + assertEquals(6, multiItemList.get(5)); + multiItemList.add(5,30); + assertEquals(30, multiItemList.get(5)); + + } + + @org.junit.jupiter.api.Test + void get() { + // Unsure how to test for indexOutOfBounds exception + assertEquals(1, singleItemList.get(0)); + assertEquals(4, multiItemList.get(3)); + } + + @org.junit.jupiter.api.Test + void set() { + // Unsure how to test for indexOutOfBounds exception + + assertFalse(singleItemList.contains(35)); + singleItemList.set(0, 35); + assertEquals(35, singleItemList.get(0)); + + assertFalse(multiItemList.contains(21)); + multiItemList.set(5, 21); + assertEquals(21, multiItemList.get(5)); + } + + @org.junit.jupiter.api.Test + void removeFront() { + // Unsure how to test for indexOutOfBounds exception + assertEquals(1, singleItemList.removeFront()); + assertEquals(1, multiItemList.removeFront()); + } + + @org.junit.jupiter.api.Test + void removeBack() { + // Unsure how to test for indexOutOfBounds exception + assertEquals(1, singleItemList.removeBack()); + assertEquals(10, multiItemList.removeBack()); + } + + @org.junit.jupiter.api.Test + void remove() { + // Unsure how to test for indexOutOfBounds exception + assertEquals(1, singleItemList.remove(0)); + assertEquals(7, multiItemList.remove(6)); + } + + @org.junit.jupiter.api.Test + void contains() { + assertFalse(emptyList.contains(2)); + assertTrue(singleItemList.contains(1)); + assertTrue(multiItemList.contains(6)); + } + + @org.junit.jupiter.api.Test + void isEmpty() { + assertTrue(emptyList.isEmpty()); + assertFalse(singleItemList.isEmpty()); + assertFalse(multiItemList.isEmpty()); + } + + @org.junit.jupiter.api.Test + void size() { + assertEquals(0, emptyList.size()); + assertEquals(1, singleItemList.size()); + assertEquals(10, multiItemList.size()); + } +} \ No newline at end of file diff --git a/tests/LinkedListTest.java b/tests/LinkedListTest.java new file mode 100644 index 0000000..317c5a3 --- /dev/null +++ b/tests/LinkedListTest.java @@ -0,0 +1,152 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedListTest { + + LinkedList emptyList = new LinkedList<>(); + LinkedList singleItem = fillList(1); + LinkedList multiItem = fillList(10); + + public LinkedList fillList(int num) { + LinkedList list = new LinkedList<>(); + for(int i = num; i > 0; i--) { + list.addFront(i); + } + return list; + } + + @Test + void addFront() { + assertEquals(0, emptyList.size()); + emptyList.addFront(27); + assertEquals(27, emptyList.get(0)); + + assertEquals(1, singleItem.get(0)); + singleItem.addFront(21); + assertEquals(21, singleItem.get(0)); + + assertEquals(1, multiItem.get(0)); + multiItem.addFront(30); + assertEquals(30, multiItem.get(0)); + } + + @Test + void addBack() { + assertEquals(0, emptyList.size()); + emptyList.addBack(27); + assertEquals(27, emptyList.get(emptyList.size() - 1)); + + assertEquals(1, singleItem.get(0)); + singleItem.addBack(21); + assertEquals(21, singleItem.get(singleItem.size() - 1)); + + assertEquals(10, multiItem.get(multiItem.size() - 1)); + multiItem.addBack(30); + assertEquals(30, multiItem.get(multiItem.size() - 1)); + } + + @Test + void add() { + assertEquals(0, emptyList.size()); + emptyList.add(0, 27); + assertEquals(27, emptyList.get(0)); + + assertEquals(1, singleItem.get(0)); + singleItem.add(0, 21); + assertEquals(21, singleItem.get(0)); + + assertEquals(10, multiItem.get(multiItem.size() - 1)); + multiItem.add(7,30); + assertEquals(30, multiItem.get(7)); + } + + @Test + void get() { + assertEquals(1, singleItem.get(0)); + + assertEquals(5, multiItem.get(4)); + } + + @Test + void set() { + assertEquals(1, singleItem.get(0)); + singleItem.set(0, 20); + assertEquals(20, singleItem.get(0)); + + assertEquals(5, multiItem.get(4)); + multiItem.set(4, 67); + assertEquals(67, multiItem.get(4)); + } + + @Test + void removeFront() { + assertEquals(1, singleItem.get(0)); + assertEquals(1, singleItem.size()); + assertEquals(1, singleItem.removeFront()); + assertEquals(0, singleItem.size()); + + assertEquals(1, multiItem.get(0)); + assertEquals(10, multiItem.size()); + assertEquals(1, multiItem.removeFront()); + assertEquals(9, multiItem.size()); + + } + + @Test + void removeBack() { + assertEquals(1, singleItem.get(0)); + assertEquals(1, singleItem.removeBack()); + + assertEquals(10, multiItem.get(multiItem.size() - 1)); + assertEquals(10, multiItem.removeBack()); + } + + @Test + void removeItem() { + Integer val = new Integer(1); + Integer val2 = new Integer(7); + + assertTrue(singleItem.contains(1)); + singleItem.remove(val); + assertEquals(0, singleItem.size()); + assertFalse(singleItem.contains(1)); + + assertTrue(multiItem.contains(7)); + multiItem.remove(val2); + assertFalse(multiItem.contains(7)); + } + + @Test + void removeIndex() { + assertTrue(singleItem.contains(1)); + singleItem.remove(0); + assertEquals(0, singleItem.size()); + assertFalse(singleItem.contains(1)); + + assertTrue(multiItem.contains(7)); + multiItem.remove(6); + assertFalse(multiItem.contains(7)); + } + + @Test + void contains() { + assertFalse(emptyList.contains(20)); + assertTrue(singleItem.contains(1)); + assertTrue(multiItem.contains(7)); + } + + @Test + void isEmpty() { + assertTrue(emptyList.isEmpty()); + assertFalse(singleItem.isEmpty()); + assertFalse(multiItem.isEmpty()); + } + + @Test + void size() { + assertEquals(0, emptyList.size()); + assertEquals(1, singleItem.size()); + assertEquals(10, multiItem.size()); + } +} \ No newline at end of file