0

I'm using Stack class for pushing List<Integer> and popping the item again back from stack:

Stack<List<Integer>> mStack = new Stack<>();

public void pushToStack(View view){
    List<Integer> mSearchResults = new ArrayList<>();
    for(int i=0; i< 10;i++){
        mSearchResults.add(i);
    }
    Log.d(TAG,"Pushing item: " + mSearchResults.size());
    mStack.push(mSearchResults);

    Log.d(TAG,"Clearing list");
    mSearchResults.clear();
    Log.d(TAG,"Size after clearing : " + mSearchResults.size());
}

I'm clearing the list after pushing to stack.

The pushToStack function outputs the logs :

Pushing item: 10

Clearing list

Size after clearing : 0

public void popFromStack(View view){
    if(mStack.size() == 0){
        Log.d(TAG,"Stack is Empty");
    }else{
        List<Integer> searchResults = mStack.pop();
        Log.d(TAG,"Result size after pop: " + searchResults.size());
    }
}

and popFromStack prints the log:

Result size after pop: 0

I wonder why mStack.pop() returns 0 as list item size instead 10.

What am I doing wrong here ?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Pankaj
  • 2,115
  • 2
  • 19
  • 39
  • 1
    You're pushing a list on the stack, and clearing that list. Why do you expect the list not to be cleared? If you put a bottle in a room, then empty that bottle, then get the bottle out of the room, it will be empty, won't it? – JB Nizet Jun 25 '17 at 08:51
  • @JBNizet java passes method arguments by value not by reference. Isn't it ? – Pankaj Jun 25 '17 at 09:01
  • 1
    The value that it passes *is* a reference. Any non-primitive variable or parameter is a *reference* to an object. See [this answer](https://stackoverflow.com/a/40523/4125191). – RealSkeptic Jun 25 '17 at 09:02

2 Answers2

2

The stack does not return the wrong item on calling pop(). The stack returns the right item. You can verify this with the following:

Log.d( TAG, "list: " + System.identityHashCode( searchResults ) );
Log.d( TAG, "list: " + System.identityHashCode( mSearchResults ) );

What happens is that a Stack<List<Integer>> contains items which are of type List<Integer> which is an Object type. In java objects are always accessed by reference, which means that a Stack<List<Integer>> contains references to list of integer.

This in turn means that when you modify the list, the stack will continue to hold a reference to it, so whatever changes you perform on the list will be visible.

Essentially, the push operation did not make a copy of the list; it just stored a reference to the one and only list that you have onto the stack.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
0

So, this is what the program is doing:

  1. Adds 10 elements in a list
  2. Pushes that list into a Stack
  3. Clears the list
  4. Pops the element from the stack and checks the size

Now, in step 2, Stack already has a reference of that list, when it gets cleared in step 3, the reference then has a list with 0 elements. So, in step 4, same (empty) list gets retrieved back and hence, sysout prints 0.

If you want that stack to retain old list then you can do

mSearchResults = new ArrayList<>();

instead of

mSearchResults.clear();
Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102