Reputation: 13
I need your help with this task:
Given a List of Integer numbers, return the average of all odd numbers from the list or throw NoSuchElementException
. But before that, subtract 1 from each element in an odd position (having the odd index). This is my solution:
return numbers.stream()
.map(i -> numbers.indexOf(i) % 2 != 0 ? i - 1 : i)
.filter(i -> i % 2 != 0)
.mapToDouble(Integer::doubleValue)
.average()
.orElseThrow(NoSuchElementException::new);
Why do I subtract 1 from the element on an even position? I need only odd positions (odd indexes). This is the picture
Upvotes: 1
Views: 486
Reputation: 7005
In your stream, you're using the indexOf
method which
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
Besides, you're mapping the stream's elements to their index, but you need to compute the average of the odd values, not the odd indexes. A better fit for your problem could be IntStream.range()
to stream the indexes of your list and then map them to their corresponding (adjusted) values.
public static Double getOddNumsAverage(List<Integer> numbers) {
return IntStream.range(0, numbers.size())
.map(index -> index % 2 != 0 ? numbers.get(index) - 1 : numbers.get(index))
.filter(value -> value % 2 != 0)
.average()
.orElseThrow(NoSuchElementException::new);
}
Upvotes: 1
Reputation: 1772
Your problem is with List#indexOf(Object)
which always returns the index of the first equal value encountered.
Now you're processing your values in a stream, so the subtracted values are returned into the stream but the original numbers
list will not be modified. When the stream processes the 5th element, which in your example is 2 again, it will look for the index in the original unmodified list and therefore numbers.indexOf( 2 )
returns index 1 which is odd and therefore i - 1
will be executed.
If you want to learn more about how to use streams with indices while avoiding such issues take a look at for example this tutorial
Upvotes: 1