开源一夏 |为什么 BigDecimal 比较大小一定要用 compareTo

日常工作中,当涉及精度较高的数值时,通常会用到 BigDecimal 类型,那么关于 BigDecimal 的比较大小更是会经常用到,在比较大小时究竟是用 compareTo 还是 equals 呢?这里我们主要来看这两种比较方式的区别,怎么选择,大家自行决定即可,哈哈。
BigDecimal
BigDecimal,是一种 java.math 包中提供的一种可以用来进行精确运算的类型,在进行金额表示、金额计算等场景,不能使用 double、float 等类型,而是要使用对精度支持的更好的 BigDecimal。
所以,很多支付、电商、金融等业务中,BigDecimal 的使用非常频繁,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的,代码中还经常需要对于数字进行相等判断。
BigDecimal 比较
==比较
==是比较常用的数值比较的方式,下面我们来看一下 BigDecimal 用==比较的结果
运行结果如图

可以看到用==直接比较肯定是无法得到自己想要的情况的,因为 BigDecimal 是对象,所以是无法用==来比较两个数字的值是否相等。
== 可以用来比较基本类型的数值,例如:

== 用来比较对象,比较的是引用对象的引用地址,针对上面的 BigDecimal 比较的情况我们来 debug 看一下
debug 结果如图

我们可以看到两个对象的引用地址不一样,所以返回 false。
equals 比较
首先来看一组代码比较结果
结果如图

通过结果可以看出 BigDecimal 在进行 equals 比较时,有的时候是 true(当使用 int、double 定义 BigDecimal 时),有的时候是 false(当使用 String 定义 BigDecimal 时)。
在 BigDecimal 的 JavaDoc 注释中提到,equals 和 compareTo 比较不太一样,equals 比较时会比较 value and scale,所以再来看上面 bigDecimal4 和 bigDecimal5 的结果就明白了

那么为什么用 int 、double 定义 BigDecimal 时就一样呢?
这里我把代码参数值改一下,方便后面 debug 区分
用 int 时 debug 结果图

其中 scale 和 xDec.scale 的值都是 0。
用 double 时 debug 结果图

其中 scale 和 xDec.scale 的值都是 0。
用 string 时 debug 结果图

其中 bigDecimal4 的 scale 是 0,而 bigDecimal5 的 scale 是 1,这样比较的结果就是 false 了。
前面,我们解释了 BigDecimal 的 equals 方法,其实不只是会比较数字的值,还会对其标度进行比较。
所以,当我们使用 equals 方法判断判断两个数是否相等的时候,是极其严格的。
compareTo 比较
针对上面 equals 比较比较严格的情况,如果只想比较值呢,BigDecimal 为我们提供了 compareTo 方法。

此时我们看到 bigDecimal6 和 bigDecimal7 比较的值为 0,即相等。
我们可以看到 BigDecimal 中 compareTo 的 JavaDoc 注释,compareTo 只比较值,其中返回结果:-1 表示小于,0 表示等于,1 表示大于

为了更好的理解 compareTo,我们来 debug 一下看看

可以看到当 scale 和 val.scale 不相等时直接进入下面数值比较,不再比较 scale 是否相等。
建议
一般 BigDecimal 值的比较用 compareTo 就好,用 equals 比较的话可能会得到不是你想要的结果而自己又不曾意识到。
版权声明: 本文为 InfoQ 作者【六月的雨在infoQ】的原创文章。
原文链接:【http://xie.infoq.cn/article/fad8c52cfa18520565d8ceb01】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论