0

I have tried for the last two days to get some code to work, first with maps and then arrayLists. It is a nested for loop that I am trying to populate a data structure with as the loops are iterated. For some reason it is filling my final data structure (an arrayList of arrayLists called DataArrays2.getCinemaRowLayout2()) with the results of the last iteration. By this I mean that ALL arrayLists that were added are ALL duplicates of the FINAL iteration. I have no idea why this is happening!

An example of 2 iterations each with a different input can be seen here: [[o, o, o, o], [o, o, o, o]]. I appreciate that it might not be the best structure to use but I am running out of time so please accept my apologies.

Any help much appreciated!

for (int i=0; i<Screens.rows; i++){//for loop of screen rows

   System.out.println("Please enter how many seats and blank spaces in this row");
   Screens.columns = Integer.valueOf(scanInValue.next());

      for(int j=0; j<Screens.columns; j++){//for loop of seats in row
        System.out.println("Please enter 'o' for a seat or press enter for a space");
        in = scanInValue.next();
        DataArrays2.getCinemaRowLayout().add(j, in);//seats in a row arraylist
      }
DataArrays2.getCinemaRowLayout2().add(i, DataArrays2.getCinemaRowLayout());//arraylist of row arraylists
DataArrays2.getCinemaRowLayout().clear();//clears seats arrayList

}
DataArrays2.getScreenMapLayout().put(showingName, DataArrays2.getCinemaRowLayout2());//map of arraylists
BookingSystem2.saveShowing(DataArrays2.getScreenMapLayout()); //saves map to file
Dan
  • 45
  • 4

2 Answers2

5

Java passing is by object reference, meaning that when you return an Object, you're returning the location in memory of that Object. So for each run through that loop, you're modifying the same ArrayList (the property of CinemaRowLayout). If you want to get a separate instance every time, you'll have to create a new ArrayList from the contents of CinemaRowLayout and add that NEW collection to the map. Right now you're adding that same object into your map over and over again, and then making changes on that object.

Alternately, you could have DataArrays2.getCinemaLayout() return a new instance every time. If that's the case, your innerLoop would look something like this:

ArrayList<whatever> temp = new ArrayList<whatever>();
for(int j=0; j<Screens.columns; j++){//for loop of seats in row
    System.out.println("Please enter 'o' for a seat or press enter for a space");
    in = scanInValue.next();
    temp.add(j, in);//seats in a row arraylist
}
DataArrays2.getCinemaRowLayout2().add(i, tmp);
JRaymond
  • 11,625
  • 5
  • 37
  • 40
  • thanks! can you explain further what you mean by 'passing is by reference'? I don't see how using the loop index 'i' creates the same result in ALL iterations if the CinemaRowLayout arrayList is cleared and populated differently each attempt...and at that it populates with the results of the most recent iteration to ALL previous attempts which just baffles me! – Dan Apr 27 '12 at 00:45
  • @Dan Are you familiar with pointers? Any time you pass an object around in java, you're really passing a pointer (or reference) to that object's location in memory. So what you're really adding to your map there at the end is a pointer to an arrayList - but all of the pointers you add to the map point to the same place! So whenever you modify something at the location being pointed to, that modification shows up anywhere you access that reference, because they're all pointing to the same spot in memory – JRaymond Apr 27 '12 at 00:48
  • cool, that is making sense now! Thanks! Any advice on how I should create a new instance every time? – Dan Apr 27 '12 at 00:50
  • @JRaymond Actually Java is always pass-by-value. When an object reference is passed as parameter, a copy of the reference is created (this is pass-by-value), it is just that now both variables (the argument and the parameter so to speak) point to the same object in memory. If Java were pass-by-reference, the modification of the reference would alter the original variable reference as well, which is not the case. – Edwin Dalorzo Apr 27 '12 at 00:56
  • @edalorzo Valid point, edited answer body to bring it more in line with reality – JRaymond Apr 27 '12 at 01:03
  • @JRaymond thanks - but I dont see the difference between the code JRaymond posted and these two lines: DataArrays2.getCinemaRowLayout().add(j, in);//seats in a row arraylist } DataArrays2.getCinemaRowLayout2().add(i, DataArrays2.getCinemaRowLayout()); both instances are arrayLists by the way.... – Dan Apr 27 '12 at 09:48
  • sorry for the last comment but I think I see it now - the new array code is nested in the loop so it is created each time.....awesome, will give it a go.... – Dan Apr 27 '12 at 10:15
  • well now for some reason all previous iterations get deleted and on the FINAL iteration is populated: output looks like this for 3 iterations: [[], [], [o, o, , ]] - then for some reason when the loop finishes everything disappears: [[], [], []] – Dan Apr 27 '12 at 10:27
  • @Dan are you still calling clear() but on temp now? That's not necessary w/ this setup – JRaymond Apr 27 '12 at 14:08
  • @JRaymond that fixed it! thanks! I wouldn't have thought it would of made any difference considering it happens after the 'storage' array is populated.... – Dan Apr 27 '12 at 14:37
  • @Dan - remember, the 'storage' is just holding where they are - Its more like an address book then a warehouse - even if somebody drives off a cliff after you put them in the address book, the address book still points to the now hospitalized person – JRaymond Apr 27 '12 at 15:27
2

Perhaps this question, Pass by value/reference, what? can help you to understand what is going on...

Community
  • 1
  • 1
Rosdi Kasim
  • 24,267
  • 23
  • 130
  • 154