Skip to content
Advertisement

why is my stack s giving null here when it has elements pushed inside it. what am i missing?

this is my code for class stackoperations in which i am working on. right now only size is implemented

***
public class MyStackOperations<T>{
private static int check_size;
    public static <T> int size(MyStack<T> s){
        // TODO implement me
        MyStack<T> temp = new MyStack<T>();
        MyStack<T> temp2 = s;
        temp = s;
        if(temp.isEmpty())
        {
            return 0;
        }
        else {
            while (!temp.isEmpty()) {
                check_size++;
                temp.pop();
            }
            return check_size;
        }

    }
***

this is my provided class that i can use from instructor. its in a different package i dont know if that makes any difference

package mystack;
/**
 * Implementing a stack using ArrayList
 * It's basically an adapter from LinkedList to Stack
 * 
 * @author Igor
 *
 */

import java.util.LinkedList;

public class MyStack<T> {

    private LinkedList<T> list;
    
    public MyStack() {
        list = new LinkedList<T>();
    }
    
    // sometimes inefficient
    public void push(T item) {
        list.addFirst(item);
    }

    public T pop() {
        return list.removeFirst();
    }
    
    public boolean isEmpty() {
        return list.size() == 0;
    }

}

this is my testing scenario

***import mystack.MyStack;
import assignment2.MyStackOperations;
import java.awt.Point;
import java.util.NoSuchElementException;


/**
 * Testing MyStackOperations
 *   
 * @author Igor
 *
 */

public class TestMyStackOperations {

public static int count=1;

public static void checkSize(int expected, int actual) {
    if (expected == actual)
        System.out.println("TestMyStackOperations " + count + ": checkEq Ok");
    else
        System.out.println("TestMyStackOperations " + count + ": checkEq Fail. "
                + "Expected size = " + expected +" but .size() returned " + actual);
    count++;
}


public static void checkPoint(Point expected, Point actual) {
    if (expected.equals(actual))
        System.out.println("TestMyStackOperations " + count + ": checkEq Ok");
    else
        System.out.println("TestMyStackOperations " + count + ": checkEq Fail");
    count++;
}

public static void main(String[] args) {
    
    MyStack<Point> s = new MyStack<Point>();
    checkSize(0, MyStackOperations.size(s));
    s.push(new Point(2,3));
    s.push(new Point(1,2));
    s.push(new Point(1,4));
    checkSize(3, MyStackOperations.size(s));
    s.push(new Point(1,2));
    s.push(new Point(6,8));
    s.push(new Point(1,2));
    s.push(new Point(3,2));
    s.push(new Point(1,4));
    s.push(new Point(5,10));

    checkSize(9, MyStackOperations.size(s));

//      Point pt0 = s.pop();
        checkSize(8, MyStackOperations.size(s));

and this is my result it shows

TestMyStackOperations 1: checkEq Ok
TestMyStackOperations 2: checkEq Ok
TestMyStackOperations 3: checkEq Ok
TestMyStackOperations 4: checkEq Fail. Expected size = 8 but .size() returned 0

why does stack s go back to zero ? are we not pushing item inside it ?

Advertisement

Answer

I see you have several mistakes in your code.

Why is returning 0 your size method?

What is happening is that you are setting a value which point to the same object in memory (it seems this is by reference, but no) When you do this:

checkSize(3, MyStackOperations.size(s));

The parameter for s is pointed to the same object in memory, that means, that if you modify that object inside the MyStackOperations.size() method, will modify also your object s (MyStack s = new MyStack())

Now, inside your MyStackOperations.size() method, you are modifying the parameter s, when you use temp.pop(); that happens because as I said, it’s a parameter which point to the same object in memory.

public static <T> int size(MyStack<T> s){
        // TODO implement me
        MyStack<T> temp = new MyStack<T>();
        MyStack<T> temp2 = s;
        temp = s;
        if(temp.isEmpty())
        {
            return 0;
        }
        else {
            while (!temp.isEmpty()) {
                check_size++;
                temp.pop();
            }
            return check_size;
        }

    }

You also have a little mistake with check_size variable, because you never reset the value, so, when you call the size method, check_size will have the last value when it was incremented.

You can test your code with a debug or you can use a simple System.out.println(s.list) each time you call MyStackOperations.size() method:

checkSize(3, MyStackOperations.size(s));
System.out.println(s.getList());
s.push(new Point(1,2));
s.push(new Point(6,8));
s.push(new Point(1,2));
s.push(new Point(3,2));
s.push(new Point(1,4));
s.push(new Point(5,10));

checkSize(9, MyStackOperations.size(s));
System.out.println(s.getList());

The s.getList() is a method which will return your linked list used inside the MyStack class. In the solution I added that method.

When you run/debug your program you will be able to see that the s object is empty.

How can you solution that?

The fastest way is use the size() method provided by the LinkedList class. In your class MyStack you will have to add a method which returns the size:

public class MyStack<T> {

    private LinkedList<T> list;
    
    public MyStack() {
        list = new LinkedList<T>();
    }
    
    public LinkedList getList(){
      return list;
    }


    // sometimes inefficient
    public void push(T item) {
        list.addFirst(item);
    }

    public T pop() {
        return list.removeFirst();
    }
    
    public boolean isEmpty() {
        return list.size() == 0;
    }

    public int size() {
        return list.size();
    }

And inside your main method, you have to checkSize like this:

MyStack<Point> s = new MyStack<Point>();
checkSize(0, s.size());
s.push(new Point(2,3));
s.push(new Point(1,2));
s.push(new Point(1,4));
checkSize(3, s.size());
....

Is there a way to fix that using your own method size?

Of course, if you want to use your own method to check the size, it’s ok! That’s no problem, it’s not recommended, but If you want you to use it, no problem. You can fix your code using the clone() method. This method is provided by Object class (all class you create inherits from Object class, and it’s not necessary to add extends Object).

So, inside your MyStack class, it must be like this:

class MyStack<T>{
LinkedList<T> list;

public MyStack()
{
    list = new LinkedList<>();
}

// sometimes inefficient
public void push(T item) {
    list.addFirst(item);
}

public T pop() {
    return list.removeFirst();
}

public boolean isEmpty() {
    return list.size() == 0;
}

public LinkedList getList()
{
    return list;
}

@Override
public MyStack<T> clone()
{
    MyStack<T> ms = new MyStack<>();
    ms.list =  (LinkedList<T>) list.clone();
    
    return ms;
}
}

It’s used list.clone(); to get a copy of the list (but not the reference now). So, if you typed ms.list=list, that will be the same objects, because it’s assigned a pointer to the same reference.

Now, inside your MyStackOperations class:

  class MyStackOperations<T>{

private static int check_size;
    public static <T> int size(MyStack<T> s){
        // TODO implement me
        check_size=0;
        if(s.isEmpty())
        {
            return 0;
        }
        else {
            while (!s.isEmpty()) {
                check_size++;
                s.pop();
            }
            return check_size;
        }

    }
}

And finally inside the main, a little example:

public static void main(String args[])
{
    MyStack<Integer> stack = new MyStack<>();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    
    System.out.println(stack.getList());
    System.out.println(MyStackOperations.size(stack.clone()));
    System.out.println(stack.getList());
}

I hope this help you! 🙂 If you have any doubt, ask the question and I will try to solve it!

2 People found this is helpful
Advertisement