Princeton1/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java

99 lines
2.4 KiB
Java

package com.hithomelabs.princeton1.module4;
import java.util.Iterator;
import javax.annotation.Nonnull;
// Concrete implementation of stack using arrays
// Creating a generic stack of type E
public class ArrayStack<E> extends Stack<E> {
// Capacity and size are two variables, capacity determines total capacity of array, capacity defaults at 10
// every time size == capacity, capacity = 2 * capacity
private static final int DEFAULT_CAPACITY = 10;
private int capacity;
private int size;
private E[] arr;
public ArrayStack(int capacity){
this.capacity = capacity;
arr = (E[]) new Object[this.capacity];
}
// Constructor chaining, default constructor will call parametrized constructor with default initial capacity 10
public ArrayStack(){
this(DEFAULT_CAPACITY);
}
@Override
public boolean isEmpty() {
return size == 0;
}
private void changeCapacity(int newCapacity){
E[] resizedArr = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++)
resizedArr[i] = arr[i];
arr = resizedArr;
}
private void incrementSize(){
if (size == capacity){
capacity = 2 * capacity;
changeCapacity(capacity);
}
}
// Push always happens at the end of the stack
// Say the size of the stack is 1, new element gets inserted at 1
@Override
public void push(E element) {
// Lazy approach, we assume size to always be lesser than capacity
incrementSize();
arr[size++] = element;
}
@Override
public E pop() {
if (isEmpty())
return null;
else{
E e = arr[--size];
arr[size] = null;
checkResize();
return e;
}
}
private void checkResize() {
if (size < capacity / 4 && capacity >= 20){
capacity = capacity / 2;
changeCapacity(capacity);
}
}
@Override
public int size() {
return size;
}
@Override
@Nonnull
public Iterator<E> iterator() {
return new Iterator<E>() {
int current = 0;
@Override
public boolean hasNext() {
return current != size;
}
@Override
public E next() {
E element = arr[current];
current = current + 1;
return element;
}
};
}
}