1

I want to add an array of integers to an ArrayList. The elements are filled with valid information under some conditions; otherwise the array is fill with -1.

    List<int []> starArray = new ArrayList<>();
    int [] star = {-1, -1, -1};
    for (int i = 0; i < 10; i++) {
        if (i < 5) {
            star[0] = i;
            star[1] = 2*i;
            star[2] = 3*i;
            starArray.add(star);
        } else {
            star[0] = star[1] = star[2] = -1;
            starArray.add(star);
        }
    }

Problem is that as soon as it goes to the else and set star = 0, all of the elements in starArray will set to -1. That means, after the loop, I get all -1 in the starArray. I want this result

0#0#0
1#2#3
2#4#6
...
-1#-1#-1

It seems that a reference is added to starArray. What I am trying to explain is that I want to create a temp array (star) with 3 elements. So star will take up 96 bytes. Then I move this 96 bytes to an ArrayList. Next I create another 3 element data in the same location of star and push another 96 bytes to ArrayList. So, by pushing two star to ArrayList, I will use

96 bytes => original star
96 bytes => first element of ArrayList
96 bytes => second element of ArrayList

So, how can I fix that?

mahmood
  • 23,197
  • 49
  • 147
  • 242

3 Answers3

4

Yes you are correct. Do not create array outside of for. Create inside and add it to list. Otherwise it keep modifies the same object multiple times and adds to the list multiple times and having the same values in the end.

for (int i = 0; i < 10; i++) {
  int [] star = {-1, -1, -1};
        if (i < 5) {
            star[0] = i;
            star[1] = 2*i;
            star[2] = 3*i;
        }
       starArray.add(star);
    }

And also remove the else completely as you are repeating the same code.


No, if you look your expected output

0#0#0
1#2#3
2#4#6
...
-1#-1#-1

All the arrays have distinct values and you still expecting one array should maintain this ? No IMHO.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
4

You're adding multiple references to the same array to the list, so changing one will inevitably change the others as well. You'll need to create a new array on each iteration:

...
for (int i = 0; i < 10; i++) {
    int[] star = {-1, -1, -1};  // create a new array each iteration
...

In your current version, the picture looks like this:

star          [...]
             /  |  \
          +---+---+---+
starArray |   |   |   |
          +---+---+---+

Notice that all references actually point to a single array in memory. Now, we're doing this:

star   [...]  [...]  [...]
           \    |    /
          +---+---+---+
starArray |   |   |   |
          +---+---+---+

i.e. we're creating multiple physical arrays that can be modified independently. Sorry for the bad ASCII art.


If you're really concerned about memory usage, one approach you could try would be having a single array for the {-1, -1, -1}s, as long as you won't be mutating these arrays in the future:

int[] starNegOne = {-1, -1, -1};
for (int i = 0; i < 10; i++) {
    if (i < 5) {
        int[] star = {i, 2*i, 3*i};
        starArray.add(star);
    } else {
        starArray.add(starNegOne);
    }
}

This saves space whenever you're adding the {-1, -1, -1} arrays.

arshajii
  • 127,459
  • 24
  • 238
  • 287
  • Please see my comment. Assume one array of 3 integers are created and then pushed to ArrayList. Will that store 6 locations in memory? – mahmood Jul 19 '17 at 18:01
  • @mahmood "Locations in memory" isn't necessarily a meaningful metric, but in general each length-3 int array takes up some constant space (12 bytes + usual array/object overhead), so creating more arrays as we're doing here will naturally use more space. – arshajii Jul 19 '17 at 18:03
3

insert a new anonymous array in every loop iteration

List<int[]> starArray = new ArrayList<>();
//int [] star = new int[];
for (int i = 0; i < 10; i++) {
    if (i < 5) {
        //star[0] = i;
        //star[1] = 2*i;
        //star[2] = 3*i;
        starArray.add(new int[]{i, 2*i, 3*i});
    } else {
        //star[0] = star[1] = star[2] = -1;
        starArray.add(new int[]{-1, -1, -1});
    }
}
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
  • Doesn't that create/new useless memory locations? I wanted to create a single array and modify it multiple times. Otherwise, I have to create the array inside the loop and for large loops, it waste memory locations. – mahmood Jul 19 '17 at 17:55
  • It might also be a good idea to just split the loop into two, with `0 ..< 5` and `5 ..< 10`. – Clashsoft Jul 19 '17 at 17:56
  • 2
    @mahmood In what way are they useless? They're storing your data. If you only add one array, you will have only one array's worth of data. – azurefrog Jul 19 '17 at 17:56
  • every new is going to place those instance on the heap, but 10 objecst are not going to kill the performance of the jvm – ΦXocę 웃 Пepeúpa ツ Jul 19 '17 at 17:56
  • You may be able to save memory by reusing the default (-1) array. – shmosel Jul 19 '17 at 17:58
  • I supposed that adding to ArrayList will also create three memory locations. For 10 iterations, your code is fine. But for large iterations, e.g. 10,000,000,000 iterations, 10B arrays (each 3 int) are stored in memory. Then another ArrayList is stored in the memory also. – mahmood Jul 19 '17 at 17:59