Mila
Mila

Reputation: 13

Java stream map, filter, and average only odd numbers

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

Answers (2)

dani-vta
dani-vta

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

L.Spillner
L.Spillner

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

Related Questions