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

Java中使用Stream筛选股票最低收盘价出错问题排查

问题:无法正确获取每只股票的最低收盘价,Stream筛选逻辑错误排查

我有一份股票交易所的CSV数据文件,读取后需按条件打印数据,要求展示每只股票的最低收盘价。但我的代码仅显示三只股票的第一条记录,无法正确获取最低值,请问我的Stream筛选逻辑哪里出错了?

我的代码

private static void smallestPriceByStock(List<String> stocks) throws ParseException {
    List<StockPrice> stockPrices = new ArrayList<>();
    HashSet<String> stock = new HashSet<>();
    SimpleDateFormat sdfOriginal = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat sdfNovaData = new SimpleDateFormat("dd/MM/yyyy");

    try {
        for (String s : stocks) {
            String[] array = a.split(",");
            String name = array[0];
            String date = array[1];
            Date dataOriginal = sdfOriginal.parse(date);
            float fechamento = Float.parseFloat(array[2]);
            long volume = Long.parseLong(array[3]);
            StockPrice stockPrice = new StockPrice(nome, dataOriginal, price, volume);
            stockPrices.add(stockPrice);
            Stock st = new Stock(name);
            st.addStockPrice(stockPrice);
            stock.add(st.getNome());

        }
        System.out.println("Menores fechamentos");
        List<Cotacao> cotas = new ArrayList<>();
        double smallestValue = 0;
        for(String a : acao) {
            for (Cotacao c : cotacoes) {
                if (c.getNome().contains(a)) {
                    smallestValue = cotacoes.stream()
                            .filter(x -> x.getNome() == a)
                            .mapToDouble(x -> x.getValue()).summaryStatistics().getMax();
                        System.out.println("Stock: " + c.getNome() + ", " + "Price: " + smallestValue + ", " + "Date: " + sdfNovaData.format(c.getData()));
                        break;
                    }
                }
            }

        for(Cotacao cotacao : cotas){
            System.out.println(cotacao.getNome());
        }
        System.out.println();
    } catch (UnsupportedOperationException | ParseException e) {
        throw new UnsupportedOperationException("calculaMenorFechamentoPorAcao não implementado", e);
    }
}

CSV文件示例

Acao,Data,Fechamento,Volume
OGXP3,2013-01-01,4.38,0
OGXP3,2013-01-02,4.76,45904000
OGXP3,2013-01-03,4.90,38143400
PETR4,2013-01-02,19.69,30182600
PETR4,2013-01-03,20.40,30552600
PETR4,2013-01-04,20.43,36141000
PETR4,2013-01-07,20.08,28069600
VALE5,2013-01-01,40.87,0
VALE5,2013-01-02,42.60,18515700
VALE5,2013-01-03,42.09,15001800
VALE5,2013-01-04,41.36,26351900

问题分析与修正

核心错误点

  1. 变量未正确初始化/引用错误

    • cotas列表全程为空,没有添加任何数据,遍历它的循环根本不会执行
    • 循环变量错误:a.split(",")中的a应该是当前循环的s;StockPrice构造器里的nome应为name,price应为fechamento
    • 未定义的变量:acao集合不存在,应该使用之前定义的stock集合
  2. Stream逻辑完全错误

    • 字符串比较用x.getNome() == a:这是引用比较,不是内容比较,应该用x.getNome().equals(a)
    • 调用getMax()而非getMin():直接取了最大值,完全违背“最低收盘价”的需求
    • 从空的cotas流中获取数据:自然得不到有效结果
  3. 流程逻辑错误

    • 即使cotas有数据,找到第一个匹配的记录就break,只会输出第一条记录,而非最低值对应的记录

修正后的代码

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

private static void smallestPriceByStock(List<String> stocks) throws ParseException {
    SimpleDateFormat sdfOriginal = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat sdfNovaData = new SimpleDateFormat("dd/MM/yyyy");

    List<StockPrice> stockPrices = new ArrayList<>();
    for (String s : stocks) {
        // 跳过CSV表头行
        if (s.startsWith("Acao")) continue;
        String[] array = s.split(",");
        String stockName = array[0];
        Date date = sdfOriginal.parse(array[1]);
        float closingPrice = Float.parseFloat(array[2]);
        long volume = Long.parseLong(array[3]);
        stockPrices.add(new StockPrice(stockName, date, closingPrice, volume));
    }

    System.out.println("Menores fechamentos");
    // 按股票名称分组,筛选出每组收盘价最低的记录
    Map<String, Optional<StockPrice>> minPriceMap = stockPrices.stream()
            .collect(Collectors.groupingBy(StockPrice::getStockName,
                    Collectors.minBy(Comparator.comparingDouble(StockPrice::getClosingPrice))));

    // 遍历输出结果
    minPriceMap.forEach((name, minPriceOpt) -> {
        minPriceOpt.ifPresent(price -> {
            System.out.printf("Stock: %s, Price: %.2f, Date: %s%n",
                    name,
                    price.getClosingPrice(),
                    sdfNovaData.format(price.getDate()));
        });
    });
}

// 配套的StockPrice实体类
class StockPrice {
    private String stockName;
    private Date date;
    private float closingPrice;
    private long volume;

    public StockPrice(String stockName, Date date, float closingPrice, long volume) {
        this.stockName = stockName;
        this.date = date;
        this.closingPrice = closingPrice;
        this.volume = volume;
    }

    public String getStockName() {
        return stockName;
    }

    public Date getDate() {
        return date;
    }

    public float getClosingPrice() {
        return closingPrice;
    }
}

修正说明

  • 先正确解析CSV数据,跳过表头,填充stockPrices列表
  • 使用Collectors.groupingBy按股票名称分组,结合Collectors.minBy和比较器,直接获取每组收盘价最低的记录
  • 用forEach遍历分组结果,输出对应股票名称、最低收盘价及对应日期
  • 修复了字符串比较、变量引用等低级错误,确保逻辑符合需求

内容的提问来源于stack exchange,提问作者Marco Aurélio Lopes Júnior

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:51:18