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
问题分析与修正
核心错误点
变量未正确初始化/引用错误
cotas列表全程为空,没有添加任何数据,遍历它的循环根本不会执行- 循环变量错误:
a.split(",")中的a应该是当前循环的s;StockPrice构造器里的nome应为name,price应为fechamento - 未定义的变量:
acao集合不存在,应该使用之前定义的stock集合
Stream逻辑完全错误
- 字符串比较用
x.getNome() == a:这是引用比较,不是内容比较,应该用x.getNome().equals(a) - 调用
getMax()而非getMin():直接取了最大值,完全违背“最低收盘价”的需求 - 从空的
cotas流中获取数据:自然得不到有效结果
- 字符串比较用
流程逻辑错误
- 即使
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
相关产品推荐
相关产品推荐

