So I recently attempted to implement a Stack using a single linked list in Java and I have this problem. If I push 100000 elements to the stack naturally, the memory increases because the stack requires 100000 nodes to store the objects. However, when the stack empties (after 100,000 pops) the references to these Nodes and their content should fall out of scope so that if the stack fills back up the memory usage should not grow. However, when this happens in my code, the memory doubles. In other words, pop does not seem to sufficiently remove references or allow for garbage collection and I am hoping that someone can tell me why.
Here is the stack class
public class Stack<T> {
private Node<T> top;
private int size;
private long limit;
public boolean isEmpty() {
return this.size == 0;
}
public void setStackLimit(long limit) {
this.limit = limit;
}
public int size() {
return size;
}
public Stack() {
this(1000L);
}
public Stack(long limit) {
this.size = 0;
this.top = null;
this.limit = limit;
}
public void push(T o) throws StackOverflowException{
if (this.size == this.limit) throw new StackOverflowException("The stack overflowed");
if (this.top == null) this.top = new Node<T>(o);
else {
Node<T> r = new Node<T>(o);
Node<T> temp = this.top;
this.top = r;
this.top.setNext(temp);
}
this.size++;
}
@SafeVarargs
public final void mpush(T... o) throws StackOverflowException{
for (T ob: o) {
this.push(ob);
}
}
public T pop() throws EmptyStackException{
if (this.top == null) throw new EmptyStackException("The stack is empty");
else {
T o = this.top.getPayload();
this.top = this.top.getNext();
this.size--;
return o;
}
}
public boolean empty() {
while (!this.isEmpty()){
try {
this.pop();
}
catch (Exception e) {
return false;
}
}
return true;
}
public String printStack() {
String stack = "";
Node<T> temp = this.top;
while (temp != null){
if (temp.getPayload() instanceof Stack<?>) {
Stack<?> stack2 = (Stack<?>)temp.getPayload();;
stack = "| " + stack2.printStack() + stack;
} else
stack = "|" + temp.getPayload().toString() + stack;
temp = temp.getNext();
}
return stack.replaceAll("[| ]$","");
}
public T peek() throws EmptyStackException {
if (this.top == null) throw new EmptyStackException("The stack is empty");
else {
T o = this.top.getPayload();
return o;
}
}
public boolean isFull() {
return this.size == this.limit;
}
public Object[] toArray() {
Object[] returnvalue = new Object[this.size];
int index = this.size-1;
Node<T> temp = this.top;
while (index >= 0) {
returnvalue[index--] = temp.getPayload();
temp = temp.getNext();
}
return returnvalue;
}
public String toString() {
try {
return "<Stack object of size " + this.size() + " last element: " + this.peek().toString() + ">";
} catch (Exception e) {
return "<Empty stack object of size " + this.size() + ">";
}
}
}
and here is the implementation of Node
public class Node<T> {
private T payload;
private Node<T> next;
public Node(T payload) {
this.payload = payload;
}
public Node<T> getNext(){
return this.next;
}
public boolean hasNext() {
return this.next != null;
}
public T getPayload() {
return this.payload;
}
public void setNext(Node<T> n) {
this.next = n;
}
public void setPayload(T o) {
this.payload = o;
}
}