1

I want to get the difference between consecutive list elements using Java stream and AtomicInteger:

List<Integer> list  = List.of(1,2,3,5,6,8,9,10,22,23,27);
AtomicInteger diff  = new AtomicInteger(1);


List<Integer> result = list.stream()
                           .skip(1)
                           .map(i -> diff.getAndSet(i - diff.get()))
                           .toList();

System.out.println(result);

Output is:

[1, 1, 2, 3, 3, 5, 4, 6, 16, 7]

I was expecting to get the difference of each element from previous like below:

[1, 1, 2, 1, 2, 1, 1, 12, 1, 4]

What am I doing wrong? How to get the desired output?

wannaBeDev
  • 516
  • 3
  • 14
  • 1
    If `diff` contains the difference, you are not calculating the difference to the previous value, but the difference to the the difference. What you actually want is, `.map(i -> i - diff.getAndSet(i))` though then, you should rename `diff` to `previous` to match the true purpose. However, that’s only to explain what’s wrong with the way you use the `AtomicInteger`, the answer suggesting to use a stream of indices instead, is the way to go. – Holger Jan 02 '23 at 13:12

1 Answers1

4

I wouldn't use an atomic type for this. Instead I would start with a stream of the list indexes:

List<Integer> result = IntStream.range(0, list.size() - 1)
                       .map(i -> list.get(i + 1) - list.get(i))
                       .boxed()
                       .toList();

Note that the ending number passed to IntStream#range is exclusive while the start is inclusive. The range is half-open.

This (IMO) is simpler and cleaner (and more functional) than relying on side-effects.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    Thank you. I had obsessed myself with working with the elements and didn't think it would be easier to work with the indexes. – wannaBeDev Dec 23 '22 at 12:40