-2

I create an arrayList and set all it's elements to 0

When all elements are set to 1, I try to turn them all back to 0 with a lambda and only the first 2 indices are changed.

// create a list freeFrames, size 5, all elements set to 0:
List<Integer> freeFrame = new ArrayList<Integer>(Collections.nCopies(5, 0));

// freeFrame= [0, 0, 0, 0, 0]

// code executes and eventually freeFrame =[1, 1, 1, 1, 1]

// try to change all values to 0 if none are present
if(!freeFrame.contains(0))
    freeFrame.forEach((b) -> freeFrame.set(b, 0));

// freeFrame= [0, 0, 1, 1, 1]

I ended up using a standard loop. Why are only the first 2 indexes getting changed with the above? This post seemed close https://stackoverflow.com/a/20040292/20419870 but I don't think I'm changing the size of the list, just changing the values. This one https://stackoverflow.com/a/56399619/20419870 suggests to use stream and map to safely modify the list while iterating. I had thought only removing and adding to list while iterating was unsafe, does modifying the contents cause an exception I'm not seeing?

vinsce
  • 1,271
  • 1
  • 10
  • 19

3 Answers3

1

There is a misuse of the forEach in your code:

freeFrame.forEach(b -> freeFrame.set(b, 0));

b here represents the value in the list, but you are using it as if it were the index (List.set wants the index as the first argument).

Suppose you start with a list l containing [1, 1, 1, 1], this is what happens running your forEach:

  1. Iteration 1:
    • b=1 (first element in the list, not first index!), you execute l.set(1,0)
    • Resulting list [1, 0, 1, 1]
  2. Iteration 2:
    • b=0 (second element in the list, changed at Iteration 1), you execute l.set(0,0)
    • Resulting list [0, 0, 1, 1]
  3. Iteration 3:
    • b=1 (third element in the list), you execute l.set(1,0)
    • Resulting list [0, 0, 1, 1] (nothing changes, it was already 0 from Iteration 1)
  4. Iteration 4:
    • b=1 (fourth element in the list), you execute l.set(1,0)
    • Resulting list [0, 0, 1, 1] (nothing changes, it was already 0 from Iteration 1)

You can easily replace all the elements in the list with a for:

for (int i = 0; i < freeFrame.size(); i++)
    freeFrame.set(i, 0);

or using streams, as you already did:

freeFrame = freeFrame.stream().map(x -> 0).collect(Collectors.toList());

but note that this solution will create a new List instead of modifying the existing list.

vinsce
  • 1,271
  • 1
  • 10
  • 19
  • Thank you so much for your time! That makes perfect sense now that I see I was using b as an index instead of the element. – Chad Lanoway Nov 05 '22 at 15:03
0

freeFrame = freeFrame.stream().map(x -> 0).collect(Collectors.toList());

worked. I referenced https://stackoverflow.com/a/56399619/20419870 before posting but got confused by a previous reply

0
if(!freeFrame.contains(0)) freeFrame.forEach((b) -> freeFrame.set(b, 0));

The logic behind this line is wrong. "b" is the element from freeFrame, java.util.List#set first parameter should be the index second parameter is the value.

You need to pass the index not the previous value.

sanurah
  • 976
  • 1
  • 6
  • 16