You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Lambda表达式比较两个Double类型列表

Hey there! 既然你已经确认两个列表的元素数量完全一致,而且想用上Lambda表达式来实现浮点数列表的比较(还得处理那些烦人的精度误差对吧?毕竟你的例子里都是接近整数但带微小偏差的double值),我给你几个实用的方案:

核心前提:别直接用==比较浮点数

首先得强调:double类型的数值不能直接用==判断相等,因为二进制存储的精度问题,像2.02.0000000001这种看似接近的数,直接用==会返回false。所以我们需要定义一个精度阈值(epsilon),当两个数的绝对差值小于这个阈值时,就认为它们相等。


方案1:Java 8 兼容版(用IntStream遍历索引)

因为Java 8没有原生的流配对方法,我们可以通过索引遍历的方式来一一对应两个列表的元素:

// 先定义精度阈值,根据你的业务场景调整,比如1e-9
double epsilon = 1e-9;

List<Double> firstList = new ArrayList<>();
firstList.add(2.0);
firstList.add(3.0);

List<Double> secondList = new ArrayList<>();
secondList.add(2.0000000001);
secondList.add(2.99999999994);

// 用Lambda结合IntStream实现比较
boolean listsAreEqual = IntStream.range(0, firstList.size())
    .allMatch(index -> Math.abs(firstList.get(index) - secondList.get(index)) < epsilon);

System.out.println(listsAreEqual); // 这里会输出true

解释:

  • IntStream.range(0, firstList.size())生成从0到列表长度-1的索引流;
  • allMatch()会检查每个索引对应的元素对是否满足「差值小于epsilon」的条件,只要有一对不满足就返回false,全部满足才返回true。

方案2:Java 9+ 更优雅的写法(用Stream.zip)

Java 9及以上新增了Stream.zip()方法,可以直接把两个流的元素一一配对,写法更直观:

double epsilon = 1e-9;

boolean listsAreEqual = Stream.zip(
        firstList.stream(),
        secondList.stream(),
        (num1, num2) -> Math.abs(num1 - num2) < epsilon
    )
    .allMatch(Boolean::booleanValue);

解释:

  • Stream.zip()把两个流的元素按顺序配对,生成一个新的流,每个元素是配对后的比较结果(boolean值);
  • 最后用allMatch()检查所有比较结果是否都是true。

进阶:高精度场景用BigDecimal

如果是金融、财务这类对精度要求极高的场景,用double的差值判断还是有风险,建议用BigDecimal来精确比较:

// 定义一个精确比较的工具方法
private static boolean isEqualWithBigDecimal(double num1, double num2) {
    // 注意:最好用字符串构造BigDecimal,避免double转BigDecimal时的精度损失
    BigDecimal bd1 = new BigDecimal(String.valueOf(num1));
    BigDecimal bd2 = new BigDecimal(String.valueOf(num2));
    return bd1.compareTo(bd2) == 0;
}

// 然后在Lambda中使用这个方法
boolean listsAreEqual = IntStream.range(0, firstList.size())
    .allMatch(index -> isEqualWithBigDecimal(firstList.get(index), secondList.get(index)));

内容的提问来源于stack exchange,提问作者Francois

火山引擎 最新活动