You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何按两个BigDecimal的差值对Quotation列表排序?

按Spread排序Quotation列表的正确实现

原代码的问题分析

  1. 比较逻辑完全错误:原代码中a.getBidPrice().intValue() - b.getAskPrice().intValue()并非比较两个Quotation对象的Spread,而是跨对象取bid和ask值相减,完全不符合需求。
  2. 直接修改原始列表:sortedBySpread = QuotationsStoreImpl.quotationList会直接操作原始数据集合,可能导致其他依赖原始列表的功能出错,应该创建副本再排序。
  3. BigDecimal转int丢失精度:如果价格包含小数(如100.5),intValue()会截断小数部分,导致Spread计算错误,必须使用BigDecimal自身的方法进行运算和比较。

正确实现代码

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class QuotationsStoreImpl {
    // 存储Quotation的原始列表
    public static List<Quotation> quotationList = new ArrayList<>();

    public static void storeQuotation(Quotation quotation) {
        quotationList.add(quotation);
    }

    public static List<Quotation> getSpreadsList(boolean decreasing) {
        // 创建原始列表的副本,避免修改原数据
        List<Quotation> sortedBySpread = new ArrayList<>(quotationList);

        // 定义按Spread升序排序的比较器
        Comparator<Quotation> spreadComparator = (a, b) -> {
            // 计算每个对象的Spread:askPrice - bidPrice
            BigDecimal spreadA = a.getAskPrice().subtract(a.getBidPrice());
            BigDecimal spreadB = b.getAskPrice().subtract(b.getBidPrice());
            // 使用BigDecimal的compareTo方法比较,保证精度和正确性
            return spreadA.compareTo(spreadB);
        };

        // 根据参数选择升序或降序排序
        Collections.sort(sortedBySpread, decreasing ? spreadComparator.reversed() : spreadComparator);

        return sortedBySpread;
    }
}

// 补充Quotation类的getter方法(原代码省略,必须实现才能访问属性)
class Quotation {
    private final long id;
    private final BigDecimal askPrice;
    private final BigDecimal bidPrice;

    public Quotation(long id, BigDecimal bidPrice, BigDecimal askPrice) {
        this.id = id;
        this.askPrice = askPrice;
        this.bidPrice = bidPrice;
    }

    public BigDecimal getAskPrice() {
        return askPrice;
    }

    public BigDecimal getBidPrice() {
        return bidPrice;
    }

    // 可选:重写toString方便验证排序结果
    @Override
    public String toString() {
        BigDecimal spread = askPrice.subtract(bidPrice);
        return String.format("id - %d.   Bid - %s.   Ask - %s.   Spread = %s", id, bidPrice, askPrice, spread);
    }
}

关键说明

  1. 列表副本保护原始数据:通过new ArrayList<>(quotationList)创建副本,排序操作不会影响原始列表。
  2. 正确计算Spread:每个Quotation对象独立计算自身的Spread(askPrice.subtract(bidPrice)),再进行两两比较。
  3. BigDecimal的compareTo方法:BigDecimal不能直接用算术运算符比较大小,compareTo方法返回-1、0、1,完全符合Comparator的返回要求,同时保证精度不丢失。
  4. 简洁处理升降序:使用spreadComparator.reversed()直接生成降序比较器,比排序后反转列表更高效。

验证结果

调用getSpreadsList(false)(升序)会得到如下排序结果:

id - 1003.   Bid - 70.   Ask - 71.   Spread = 1
id - 1006.   Bid - 92.   Ask - 93.   Spread = 1
id - 1004.   Bid - 71.   Ask - 73.   Spread = 2
id - 1008.   Bid - 90.   Ask - 92.   Spread = 2
id - 1001.   Bid - 69.   Ask - 72.   Spread = 3
id - 1009.   Bid - 92.   Ask - 95.   Spread = 3
id - 1002.   Bid - 65.   Ask - 69.   Spread = 4
id - 1007.   Bid - 94.   Ask - 98.   Spread = 4
id - 1000.   Bid - 99.   Ask - 104.   Spread = 5
id - 1005.   Bid - 90.   Ask - 95.   Spread = 5

调用getSpreadsList(true)(降序)则会得到完全相反的顺序。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:40:34