Java/Groovy中List.contains()比较Double值返回false问题求解
问题原因与解决方案
根本原因
- 你所使用的Groovy语法中,默认浮点字面量
8.42431001E10的类型是BigDecimal,而非getSomeValue方法返回的Double类型 - List的
contains方法基于equals方法实现,不同数值类型即使字面量值相同,equals对比也会返回false,这是表达式不符合预期的核心原因 - 转String后对比生效,是因为二者的字符串表示完全一致,绕开了类型差异的限制
可落地解决方案
方案1:对齐列表元素类型为Double(改动最小)
直接将列表中的浮点字面量强制转为Double,和返回值类型匹配:
[8.42431001E10 as Double].contains(getSomeValue('000000084243100100'))
也可以显式构造Double对象:
[Double.valueOf("8.42431001E10")].contains(getSomeValue('000000084243100100'))
方案2:将待比较值转为BigDecimal对齐列表类型
如果不想修改列表定义,可将getSomeValue的返回值转为BigDecimal:
[8.42431001E10].contains(new BigDecimal(getSomeValue('000000084243100100').toString()))
方案3:统一数值类型为BigDecimal(推荐,长期稳定)
修改getSomeValue方法,统一返回BigDecimal类型,既适配Groovy默认浮点类型,也能避免Double的精度丢失问题:
public Object getSomeValue(String value) { if (NumberUtils.isNumber(value)) { try { result = new BigDecimal(value); } catch (Exception e) { result = value; } } else { result = value; } return result; }
修改后原表达式无需额外改动即可返回true。
方案4:自定义数值比较逻辑(适配精度误差场景)
如果是Double精度误差导致的数值不一致,可采用误差范围比较,绕过严格的equals限制:
double target = ((Number)getSomeValue('000000084243100100')).doubleValue(); boolean isExist = [8.42431001E10].any { num -> Math.abs(num.doubleValue() - target) < 1e-9 }
内容的提问来源于stack exchange,提问作者Code Geek
相关产品推荐
相关产品推荐

