Task Generics: GenericStack Class. Java and JUnit5 (Unit test)
package Modul02;
public class GenericStack<E> {
private java.util.ArrayList<E> list = new java.util.ArrayList<>();
public int size() {
return list.size();
}
public E peek() {
return list.get(size() - 1);
}
public void push(E o) {
list.add(o);
}
public E pop() {
E o = list.get(size() - 1);
list.remove(size() - 1);
return o;
}
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public String toString() {
return "stack: " + list.toString();
}
}
package Modul02;
public class TestGenericStack {
public static void main(String[] args) {
GenericStack gsString = new GenericStack<>();
gsString.push("one");
gsString.push("two");
gsString.push("three");
while (!(gsString.isEmpty())) {
System.out.println(gsString.pop());
}
GenericStack gsInteger = new GenericStack<>();
gsInteger.push(1);
gsInteger.push(2);
gsInteger.push(3);
//gsInteger.push("4");
while (!(gsInteger.isEmpty())) {
System.out.println(gsInteger.pop());
}
}
}
Create a new version of GenericStack that uses an array instead of an ArrayList (this version should also be generic). Be sure to check the size of the array before adding a new item; - if the array becomes full, double the size of the array, and you must copy elements from the old array to the new one.
Note that one cannot use the new operator on a generic type, new E is not allowed.
In order to create the array of the generic type, one must cast:
private E [] elements = (E[]) new Object[100];
Important that push checks that there is enough space, if not you have to double the stack size before push. Pushes should also not allow zero values as arguments, because now they should only be ignored.
Tips: System.arraycopy (...); Public interface for the class is known, but start writing the tests first.
JUnit5(Unit test) Write tests: The tests will cover all scenarios (all possible ways you can use a stack). Since this is a generic class, test it for at least two different types (What if someone uses pop or peek on a blank stack?). Remember to include a test where the stack must be doubled to accommodate a new push (). Feel free to introduce a new public method capacity () that responds to the stack's current capacity. Also, create (if you haven't done) a constructor for the stack that takes in startup capacity (before you have one that creates a default capacity).
Here is the completed code for this problem. Comments are included, go through it, learn how things work and let me know if you have any doubts or if you need anything to change. If you are satisfied with the solution, please rate the answer. Thanks
Edit: JUnit test class is added.
// GenericStack.java
public class GenericStack<E> {
// array
private E[] array;
// current size
private int size;
// initial capacity
private final int DEFAULT_CAPACITY = 10;
// constructor initializes an array of default capacity
public GenericStack() {
array = (E[]) new Object[DEFAULT_CAPACITY];
// initializing size to 0
size = 0;
}
// returns the size
public int size() {
return size;
}
// returns top element; or null if empty
public E peek() {
if (isEmpty()) {
// empty
return null;
}
// returning current top element
return array[size - 1];
}
// adds an element to the top
public void push(E o) {
// preventing addition of null values
if (o != null) {
// if array is full, doubling it
if (size == array.length) {
// creating new array of twice capacity
E[] newArr = (E[]) new Object[size * 2];
// copying array to newArr
System.arraycopy(array, 0, newArr, 0, array.length);
// replacing old array with new one
array = newArr;
}
// adding to index
array[size] = o;
// updating index
size++;
}
}
// removes and returns the top element from stack, or null if empty
public E pop() {
if (isEmpty()) {
// empty stack
return null;
}
// getting element at top
E element = array[size - 1];
// updating size
size--;
// returning removed element
return element;
}
// returns true if stack is empty
public boolean isEmpty() {
return size == 0;
}
@Override
public String toString() {
String str = "stack: [";
// appending all elements of stack to a String
for (int i = 0; i < size; i++) {
str += array[i];
if (i != size - 1) {
// appending a comma and space if this is not last element
str += ", ";
}
}
str += "]";
return str;
}
}
//modified TestGenericStack class to include more tests
public class TestGenericStack {
public static void main(String[] args) {
GenericStack<String> gsString = new GenericStack<String>();
System.out.println("Current top element: " + gsString.peek());
gsString.push("one");
gsString.push("two");
gsString.push(null); // will not be added since element is null
gsString.push("three");
System.out.println("Current top element: " + gsString.peek());
System.out.println("popping until empty");
while (!(gsString.isEmpty())) {
System.out.println(gsString.pop());
}
// attempting to pop an empty stack, should display null
System.out.println("pop on empty stack: " + gsString.pop());
GenericStack<Integer> gsInteger = new GenericStack<Integer>();
System.out.println("Current top element: " + gsInteger.peek());
// adding numbers from 1 to 20 to integer stack
for (int i = 1; i <= 20; i++) {
gsInteger.push(i);
}
gsInteger.push(null); // will not be added since element is null
System.out.println("Current top element: " + gsInteger.peek());
while (!(gsInteger.isEmpty())) {
System.out.println(gsInteger.pop());
}
// attempting to pop an empty stack, should display null
System.out.println("pop on empty stack: " + gsInteger.pop());
}
}
// GenericStackTest.java (JUnit test)
import static org.junit.Assert.*;
import org.junit.Test;
public class GenericStackTest {
private GenericStack<Integer> stack;
@Test
public void testGenericStackConstructor() {
// ensuring that constructor creates an empty stack
stack = new GenericStack<Integer>();
assertEquals(stack.size(), 0);
assertEquals(stack.isEmpty(), true);
assertEquals(stack.toString(), "stack: []");
}
@Test
public void testSize() {
// ensuring that stack size is 0 initially and increments after every
// push operation
stack = new GenericStack<Integer>();
assertEquals(stack.size(), 0);
stack.push(1);
assertEquals(stack.size(), 1);
for (int i = 1; i < 100; i++) {
stack.push(i);
}
// after 100 valid push(), ensuring that size is 100
assertEquals(stack.size(), 100);
}
@Test
public void testPeek() {
// ensuring that peek method always return top value, or null if stack
// is empty
stack = new GenericStack<Integer>();
assertEquals(stack.peek(), null);
stack.push(1);
assertEquals(stack.peek(), (Integer) 1);
stack.push(999);
assertEquals(stack.peek(), (Integer) 999);
}
@Test
public void testPush() {
// ensuring that push method always add elements to the top
stack = new GenericStack<Integer>();
for (int i = 0; i < 100; i++) {
stack.push(i);
assertEquals(stack.peek(), (Integer) i);
}
}
@Test
public void testPop() {
stack = new GenericStack<Integer>();
//adding elements from 0 to 100 to stack
for (int i = 0; i <= 100; i++) {
stack.push(i);
}
//ensuring that elements are popped in reverse order
for (int i = 100; i >= 0; i--) {
assertEquals(stack.pop(), (Integer) i);
}
}
@Test
public void testIsEmpty() {
//ensuring that isEmpty works as needed
stack = new GenericStack<Integer>();
assertEquals(stack.isEmpty(), true);
stack.push(1234);
assertEquals(stack.isEmpty(), false);
stack.pop();
assertEquals(stack.isEmpty(), true);
}
@Test
public void testToString() {
//thoroughly testing toString method of the stack
stack = new GenericStack<Integer>();
assertEquals(stack.toString(), "stack: []");
stack.push(1234);
assertEquals(stack.toString(), "stack: [1234]");
stack.push(999);
assertEquals(stack.toString(), "stack: [1234, 999]");
stack.push(0);
assertEquals(stack.toString(), "stack: [1234, 999, 0]");
stack.pop();
assertEquals(stack.toString(), "stack: [1234, 999]");
stack.pop();
assertEquals(stack.toString(), "stack: [1234]");
stack.pop();
assertEquals(stack.toString(), "stack: []");
}
}
/*OUTPUT*/
Current top element: null
Current top element: three
popping until empty
three
two
one
pop on empty stack: null
Current top element: null
Current top element: 20
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
pop on empty stack: null
Get Answers For Free
Most questions answered within 1 hours.