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 thesize
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 theMyStack
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 typedms.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!