偶数的平均值会返回错误的值

时间:2019-01-02 14:27:29

标签: java lambda java-stream

我正试图更加了解流,因此我正在做一些基本练习。在此,我想计算奇数的平均值。我为此编写了算法,但返回的结果不正确(8.0)。我尝试调试它,但实际上找不到它。

List<Integer> numbers = Arrays.asList(1, 3, -2, -4, -7, -3, -8, 12, 19, 6, 9, 10, 14);

OptionalDouble result = numbers.stream()
                               .filter(i -> i % 2 == 1)
                               .mapToDouble(i -> i).average();
if (result.isPresent()) {
   System.out.println(result);
} else {
   System.out.println("Error");
}

我的代码现在在做什么?我应该如何解决它应做的事?

3 个答案:

答案 0 :(得分:11)

(i -> i % 2 == 1)

这仅适用于正奇数,因为在Java中,%运算符的第一个操作数为负数时将返回负数(或零)。

如果您只想保留偶数数字,则应为:

(i -> i % 2 == 0)

如果要保留所有奇数(正数和负数),可以使用:

(i -> i % 2 != 0)

答案 1 :(得分:3)

  

我的代码现在在做什么?

您正在执行modulo operation on negative number

  

我应该如何解决它应做的事?

您可以使用Math.abs来验证列表中的绝对值是否为奇数:

OptionalDouble result = numbers.stream()
                .filter(i -> Math.abs(i) % 2 == 1) // verify id the absolute value is odd
                .mapToDouble(i->i).average();

答案 2 :(得分:2)

除了@khelwood提到的带负数模的内容之外。

重要的是要知道,filter中间操作不会删除元素,也不会进行任何流操作,相反,filter返回一个新的流,其中所有元素满足提供的谓词,即i -> i % 2 == 1

i -> i % 2 == 1表示“如果元素是奇数,则仅将其表示为i”。

如果您愿意的话,甚至应该执行i -> i % 2 == 0,读为“仅保留表示为i的元素,因为它是偶数”。


另一方面,如果您在JDK9上运行,则可以使用ifPresentOrElse来简单地进行isPresent()检查。

 numbers.stream()
        .filter(i -> i % 2 == 0)
        .mapToDouble(i -> i)
        .average()
        .ifPresentOrElse(System.out::println,
                        () -> System.out.println("Error"));