Java8的Stream中的Collectors操作求double类型和的坑

无敌踩坑王的我又双叒叕来了!!!!!!

例子:

    @Testpublic void testSumDouble() {double a = 0.001;double b = 0.002;double c = 0.004;List<Double> doubleList = new ArrayList<>();doubleList.add(a);doubleList.add(b);double sum = doubleList.stream().collect(Collectors.summarizingDouble(Double::shortValue)).getSum();System.out.println(sum);if (c > sum) {System.out.println("sum:" + sum + "小于" + "c:" + c);}}

一、场景,统计double类型的数值进行计算

二、计算

感觉这个结果应该是什么样子的?

是不是应该输出的是小于的

是的,输出的就是小于的,但是值确是这样的

0.0
sum:0.0小于c:0.004

是不是与预期的不符?

接下来我们看一下他的底层的定义

     计算用的方法Collectors.summarizingDouble(Double::shortValue)summarizingDouble实现的方法public static <T>Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(DoubleSummaryStatistics::new,(r, t) -> r.accept(mapper.applyAsDouble(t)),(l, r) -> { l.combine(r); return l; }, CH_ID);}

DoubleSummaryStatistics 类的代码

/** Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/
package java.util;import java.util.function.DoubleConsumer;
import java.util.stream.Collector;public class DoubleSummaryStatistics implements DoubleConsumer {private long count;private double sum;private double sumCompensation; // Low order bits of sumprivate double simpleSum; // Used to compute right sum for non-finite inputsprivate double min = Double.POSITIVE_INFINITY;private double max = Double.NEGATIVE_INFINITY;/*** Construct an empty instance with zero count, zero sum,* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}* max and zero average.*/public DoubleSummaryStatistics() { }/*** Records another value into the summary information.** @param value the input value*/@Overridepublic void accept(double value) {++count;simpleSum += value;sumWithCompensation(value);min = Math.min(min, value);max = Math.max(max, value);}public void combine(DoubleSummaryStatistics other) {count += other.count;simpleSum += other.simpleSum;sumWithCompensation(other.sum);sumWithCompensation(other.sumCompensation);min = Math.min(min, other.min);max = Math.max(max, other.max);}private void sumWithCompensation(double value) {double tmp = value - sumCompensation;double velvel = sum + tmp; // Little wolf of rounding errorsumCompensation = (velvel - sum) - tmp;sum = velvel;}/*** Return the count of values recorded.** @return the count of values*/public final long getCount() {return count;}public final double getSum() {// Better error bounds to add both terms as the final sumdouble tmp =  sum + sumCompensation;if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))// If the compensated sum is spuriously NaN from// accumulating one or more same-signed infinite values,// return the correctly-signed infinity stored in// simpleSum.return simpleSum;elsereturn tmp;}public final double getMin() {return min;}public final double getMax() {return max;}public final double getAverage() {return getCount() > 0 ? getSum() / getCount() : 0.0d;}@Overridepublic String toString() {return String.format("%s{count=%d, sum=%f, min=%f, average=%f, max=%f}",this.getClass().getSimpleName(),getCount(),getSum(),getMin(),getAverage(),getMax());}
}

Double类的代码

/** Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/package java.lang;import sun.misc.FloatingDecimal;
import sun.misc.FpUtils;
import sun.misc.DoubleConsts;public final class Double extends Number implements Comparable<Double> {/*** A constant holding the positive infinity of type* {@code double}. It is equal to the value returned by* {@code Double.longBitsToDouble(0x7ff0000000000000L)}.*/public static final double POSITIVE_INFINITY = 1.0 / 0.0;/*** A constant holding the negative infinity of type* {@code double}. It is equal to the value returned by* {@code Double.longBitsToDouble(0xfff0000000000000L)}.*/public static final double NEGATIVE_INFINITY = -1.0 / 0.0;/*** A constant holding a Not-a-Number (NaN) value of type* {@code double}. It is equivalent to the value returned by* {@code Double.longBitsToDouble(0x7ff8000000000000L)}.*/public static final double NaN = 0.0d / 0.0;/*** A constant holding the largest positive finite value of type* {@code double},* (2-2<sup>-52</sup>)&middot;2<sup>1023</sup>.  It is equal to* the hexadecimal floating-point literal* {@code 0x1.fffffffffffffP+1023} and also equal to* {@code Double.longBitsToDouble(0x7fefffffffffffffL)}.*/public static final double MAX_VALUE = 0x1.fffffffffffffP+1023; // 1.7976931348623157e+308/*** A constant holding the smallest positive normal value of type* {@code double}, 2<sup>-1022</sup>.  It is equal to the* hexadecimal floating-point literal {@code 0x1.0p-1022} and also* equal to {@code Double.longBitsToDouble(0x0010000000000000L)}.** @since 1.6*/public static final double MIN_NORMAL = 0x1.0p-1022; // 2.2250738585072014E-308/*** A constant holding the smallest positive nonzero value of type* {@code double}, 2<sup>-1074</sup>. It is equal to the* hexadecimal floating-point literal* {@code 0x0.0000000000001P-1022} and also equal to* {@code Double.longBitsToDouble(0x1L)}.*/public static final double MIN_VALUE = 0x0.0000000000001P-1022; // 4.9e-324/*** Maximum exponent a finite {@code double} variable may have.* It is equal to the value returned by* {@code Math.getExponent(Double.MAX_VALUE)}.** @since 1.6*/public static final int MAX_EXPONENT = 1023;/*** Minimum exponent a normalized {@code double} variable may* have.  It is equal to the value returned by* {@code Math.getExponent(Double.MIN_NORMAL)}.** @since 1.6*/public static final int MIN_EXPONENT = -1022;/*** The number of bits used to represent a {@code double} value.** @since 1.5*/public static final int SIZE = 64;/*** The number of bytes used to represent a {@code double} value.** @since 1.8*/public static final int BYTES = SIZE / Byte.SIZE;/*** The {@code Class} instance representing the primitive type* {@code double}.** @since JDK1.1*/@SuppressWarnings("unchecked")public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");public static String toString(double d) {return FloatingDecimal.toJavaFormatString(d);}public static String toHexString(double d) {/** Modeled after the "a" conversion specifier in C99, section* 7.19.6.1; however, the output of this method is more* tightly specified.*/if (!isFinite(d) )// For infinity and NaN, use the decimal output.return Double.toString(d);else {// Initialized to maximum size of output.StringBuilder answer = new StringBuilder(24);if (Math.copySign(1.0, d) == -1.0)    // value is negative,answer.append("-");                  // so append sign infoanswer.append("0x");d = Math.abs(d);if(d == 0.0) {answer.append("0.0p0");} else {boolean subnormal = (d < DoubleConsts.MIN_NORMAL);// Isolate significand bits and OR in a high-order bit// so that the string representation has a known// length.long signifBits = (Double.doubleToLongBits(d)& DoubleConsts.SIGNIF_BIT_MASK) |0x1000000000000000L;// Subnormal values have a 0 implicit bit; normal// values have a 1 implicit bit.answer.append(subnormal ? "0." : "1.");// Isolate the low-order 13 digits of the hex// representation.  If all the digits are zero,// replace with a single 0; otherwise, remove all// trailing zeros.String signif = Long.toHexString(signifBits).substring(3,16);answer.append(signif.equals("0000000000000") ? // 13 zeros"0":signif.replaceFirst("0{1,12}$", ""));answer.append('p');// If the value is subnormal, use the E_min exponent// value for double; otherwise, extract and report d's// exponent (the representation of a subnormal uses// E_min -1).answer.append(subnormal ?DoubleConsts.MIN_EXPONENT:Math.getExponent(d));}return answer.toString();}}public static Double valueOf(String s) throws NumberFormatException {return new Double(parseDouble(s));}public static Double valueOf(double d) {return new Double(d);}public static double parseDouble(String s) throws NumberFormatException {return FloatingDecimal.parseDouble(s);}public static boolean isNaN(double v) {return (v != v);}public static boolean isInfinite(double v) {return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);}public static boolean isFinite(double d) {return Math.abs(d) <= DoubleConsts.MAX_VALUE;}private final double value;public Double(double value) {this.value = value;}public Double(String s) throws NumberFormatException {value = parseDouble(s);}/*** Returns {@code true} if this {@code Double} value is* a Not-a-Number (NaN), {@code false} otherwise.** @return  {@code true} if the value represented by this object is*          NaN; {@code false} otherwise.*/public boolean isNaN() {return isNaN(value);}/*** Returns {@code true} if this {@code Double} value is* infinitely large in magnitude, {@code false} otherwise.** @return  {@code true} if the value represented by this object is*          positive infinity or negative infinity;*          {@code false} otherwise.*/public boolean isInfinite() {return isInfinite(value);}public String toString() {return toString(value);}/*** Returns the value of this {@code Double} as a {@code byte}* after a narrowing primitive conversion.** @return  the {@code double} value represented by this object*          converted to type {@code byte}* @jls 5.1.3 Narrowing Primitive Conversions* @since JDK1.1*/public byte byteValue() {return (byte)value;}/*** Returns the value of this {@code Double} as a {@code short}* after a narrowing primitive conversion.** @return  the {@code double} value represented by this object*          converted to type {@code short}* @jls 5.1.3 Narrowing Primitive Conversions* @since JDK1.1*/public short shortValue() {return (short)value;}/*** Returns the value of this {@code Double} as an {@code int}* after a narrowing primitive conversion.* @jls 5.1.3 Narrowing Primitive Conversions** @return  the {@code double} value represented by this object*          converted to type {@code int}*/public int intValue() {return (int)value;}/*** Returns the value of this {@code Double} as a {@code long}* after a narrowing primitive conversion.** @return  the {@code double} value represented by this object*          converted to type {@code long}* @jls 5.1.3 Narrowing Primitive Conversions*/public long longValue() {return (long)value;}/*** Returns the value of this {@code Double} as a {@code float}* after a narrowing primitive conversion.** @return  the {@code double} value represented by this object*          converted to type {@code float}* @jls 5.1.3 Narrowing Primitive Conversions* @since JDK1.0*/public float floatValue() {return (float)value;}/*** Returns the {@code double} value of this {@code Double} object.** @return the {@code double} value represented by this object*/public double doubleValue() {return value;}@Overridepublic int hashCode() {return Double.hashCode(value);}/*** Returns a hash code for a {@code double} value; compatible with* {@code Double.hashCode()}.** @param value the value to hash* @return a hash code value for a {@code double} value.* @since 1.8*/public static int hashCode(double value) {long bits = doubleToLongBits(value);return (int)(bits ^ (bits >>> 32));}public boolean equals(Object obj) {return (obj instanceof Double)&& (doubleToLongBits(((Double)obj).value) ==doubleToLongBits(value));}public static long doubleToLongBits(double value) {long result = doubleToRawLongBits(value);// Check for NaN based on values of bit fields, maximum// exponent and nonzero significand.if ( ((result & DoubleConsts.EXP_BIT_MASK) ==DoubleConsts.EXP_BIT_MASK) &&(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)result = 0x7ff8000000000000L;return result;}public static native long doubleToRawLongBits(double value);public static native double longBitsToDouble(long bits);public int compareTo(Double anotherDouble) {return Double.compare(value, anotherDouble.value);}public static int compare(double d1, double d2) {if (d1 < d2)return -1;           // Neither val is NaN, thisVal is smallerif (d1 > d2)return 1;            // Neither val is NaN, thisVal is larger// Cannot use doubleToRawLongBits because of possibility of NaNs.long thisBits    = Double.doubleToLongBits(d1);long anotherBits = Double.doubleToLongBits(d2);return (thisBits == anotherBits ?  0 : // Values are equal(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)1));                          // (0.0, -0.0) or (NaN, !NaN)}/*** Adds two {@code double} values together as per the + operator.** @param a the first operand* @param b the second operand* @return the sum of {@code a} and {@code b}* @jls 4.2.4 Floating-Point Operations* @see java.util.function.BinaryOperator* @since 1.8*/public static double sum(double a, double b) {return a + b;}public static double max(double a, double b) {return Math.max(a, b);}/*** Returns the smaller of two {@code double} values* as if by calling {@link Math#min(double, double) Math.min}.** @param a the first operand* @param b the second operand* @return the smaller of {@code a} and {@code b}.* @see java.util.function.BinaryOperator* @since 1.8*/public static double min(double a, double b) {return Math.min(a, b);}/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -9172774392245257468L;
}

到这里应该就很明显了

我们可以发现,我们使用这个方法去做计算的时候,默认走的底层逻辑是Double这个类,之所以出现问题,是因为Double类定义了几个final修饰的量

    public static final double POSITIVE_INFINITY = 1.0 / 0.0;/*** A constant holding the negative infinity of type* {@code double}. It is equal to the value returned by* {@code Double.longBitsToDouble(0xfff0000000000000L)}.*/public static final double NEGATIVE_INFINITY = -1.0 / 0.0;/*** A constant holding a Not-a-Number (NaN) value of type* {@code double}. It is equivalent to the value returned by* {@code Double.longBitsToDouble(0x7ff8000000000000L)}.*/public static final double NaN = 0.0d / 0.0;

导致的只能计算出小数点后一位的精准值,如果定义的有小数点后两位的数据,会导致数值不准确,不相信的小伙伴可以自己尝试一下

当然这种的数据也是有办法处理的,确定小数点后几位的数据,乘以较大的整数比如10000,先计算,计算完之后进行除法计算,就能得到真实的值

如果你有好的方法也可以贴出来告诉我,共同学习,共同进步

认个错,可以使用下面三种进行计算

double sum1 = doubleList.stream().collect(Collectors.summarizingDouble(Double::doubleValue)).getSum();
double sum2 = doubleList.stream().collect(Collectors.summarizingDouble(Double::valueOf)).getSum();
double sum3 = doubleList.stream().collect(Collectors.summarizingDouble(Double::new)).getSum();

使用下面这个是同样的结果

double sum1 = doubleList.stream().collect(Collectors.summingDouble(Double::doubleValue)).getSum();
double sum2 = doubleList.stream().collect(Collectors.summingDouble(Double::valueOf)).getSum();
double sum3 = doubleList.stream().collect(Collectors.summingDouble(Double::new)).getSum();

更好的方案依然可以贴出来

Java8的Stream中的Collectors操作求double类型和的坑相关推荐

  1. java8的stream中的toMap

    我们将对这个List使用java8的strea中的toMap转换成Map对象. toMap有个三个重载的方法,toConcurrentMap同理: 两个参数 public static <T, ...

  2. Java8流Stream的创建和操作

    1. 流的创建方法 import java.util.stream.*;public class StreamOf {public static void main(String[] args) {S ...

  3. JPA学习笔记---JPA实体Bean的建立---链接上一个博文:对实体Bean中属性进行操作:保存日期类型,设置字段的长度,名字,是否为空,可以声明枚举字段;可以存放二进制数据,可以存放

    3.给上述生成的那个name字段:更改数据库中的字段名,是否为空,字段长度的设定,只需要   在Person.java文件中,加上 @Column(length=10,nullable=false,n ...

  4. java double转换符_java中字符串怎么转换成double类型

    展开全部 public class Demo { public static void main(String[] args) { Demo demo = new Demo(); String str ...

  5. 求double类型的立方根_二分法逼近

    import java.util.Scanner; public class Main {public static void main(String[] args){Scanner scanner ...

  6. java8的lambda中的map相关操作

    0 入门详解篇 1   史上最简单入门:java8的lambda中的map相关操作:基础及注意事项图文详解 2   java8的lambda中collect接口案例及原理详解,官方文档解读 3   j ...

  7. Java8的 Stream 流的各种用法

    Java8 的 Stream 流的各种用法 什么是Stream 1. Stream可以由数组或集合创建,对流的操作分为两种 2. Stream的特性 3. Stream可以通过集合数组创建 4. st ...

  8. Java8 的 Stream简单教程

    Stream 流 一.什么是Stream? Stream 将要处理的元素集合看作一种流, 在流的过程中,借助Steam API 对流中的元素进行操作,比如:筛选.排序.聚合等. Stream 可以由数 ...

  9. 对 Stream 中 Map 与 ForEach 做个简单说明

    经常会有童鞋把 Map 和 Foreach 用错,可能会出现如下用法: List<Student> studentChangeList = studentList.stream().for ...

最新文章

  1. Python的闭包和装饰器
  2. oracle数据库结束进程后怎么重启,Oracle数据库的启动与关闭方法
  3. mysql的基准测试_mysql基准测试 -benchmarks
  4. 基于Spring Boot配置文件的日志记录示例样本
  5. 洛谷 P1767 家族_NOI导刊2010普及(10)
  6. 高等数学同济第七版上册电子版_高等数学同济第七版(上册)第一章答案
  7. linux cpu频率软件,linux cpu频率控制
  8. pycharm引入其他目录的包报错,import报错
  9. 深度学习模型在训练集上很好而在测试集表现得不好而拟合次数并不多_机器学习中的过拟合,欠拟合和偏倚方差折衷...
  10. c语言万能源代码,经典C语言源代码
  11. NAS个人云存储服务器搭建
  12. 基于.net开发chrome核心浏览器【六】
  13. 关于Video Src 带有 blob:http的视频如何下载的问题
  14. java设计模式(1)
  15. 学员管理系统(面向对象版)
  16. Neo4j学习笔记(三) 导入数据
  17. Rviz 实现 pannel 插件
  18. 本地blast详细用法
  19. 如何辨别优劣高防服务器?
  20. 【虾皮选品趋势】盘点马来和新加坡市场雨季热销产品

热门文章

  1. XCode7打开XCode8项目的Storyboard
  2. 未来教育python全程班百度云_2019、3未来教育等级考试
  3. 动手实现2d游戏引擎(一)
  4. CSDN换了新的logo
  5. 利用bootstrap写的后台管理系统主页模板
  6. ubuntu之截图工具Flameshot
  7. java毕业设计劳务外包管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  8. Manjaro安装Mariadb
  9. 矩阵对矩阵求导,标量对矩阵求导,链式法则
  10. IP、子网、等如何计算?