如何按元素逐个合并多个同规模的Queue集合?
问题描述
我有3个规模相同、按日期排序的记录队列(Queue),想要将它们按顺序逐个合并。示例代码定义了如下记录类型和队列:
record BuyOrder(String date, String product, double buyPx) {}; record SellOrder(String date, double sellPx) {}; record Transaction(String date, double commission, int volume) {}; record Combined(BuyOrder b, SellOrder s, Transaction t); Queue<BuyOrder> buys = new LinkedList<>(); Queue<SellOrder> sells = new LinkedList<>(); Queue<Transaction> transactions = new LinkedList<>(); Queue<Combined> combined = new LinkedList<>();
需要用这3个队列的元素创建combined队列,每个Combined对应的输出格式为[date, product, buyPx, sellPx, commission, volume], [date, product, buyPx, sellPx, commission, volume], ...。
我目前用循环实现的代码如下:
@assert (buys.size() == sells.size() && sells.size() == transactions.size()); for (BuyOrder buy: buys) { SellOrder sell = sells.poll(); // 移除队首元素 Transaction transaction = transactions.poll(); combined.add(new Combined(buy, sell, transaction)); }
但我觉得应该有更高效简洁的实现方式,比如用stream(),请问该怎么实现?
基于Stream的实现方案
Java标准Stream API本身没有原生支持多流并行遍历的方法,但可以通过以下几种方式实现需求:
方式1:利用迭代器+Stream.generate(不修改原队列)
如果不需要清空原队列,可通过迭代器遍历元素,配合Stream.generate生成合并后的流:
import java.util.Iterator; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; // 获取三个队列的迭代器 Iterator<BuyOrder> buyIter = buys.iterator(); Iterator<SellOrder> sellIter = sells.iterator(); Iterator<Transaction> transIter = transactions.iterator(); // 生成合并流并收集到队列中 Queue<Combined> combined = Stream.generate(() -> { if (buyIter.hasNext() && sellIter.hasNext() && transIter.hasNext()) { return new Combined(buyIter.next(), sellIter.next(), transIter.next()); } return null; }) .takeWhile(Objects::nonNull) .collect(Collectors.toCollection(LinkedList::new));
方式2:利用poll()+Stream.generate(清空原队列)
如果需要合并后清空原队列(和你原循环逻辑一致),可以在Stream中直接调用poll():
import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; Queue<Combined> combined = Stream.generate(() -> { BuyOrder buy = buys.poll(); SellOrder sell = sells.poll(); Transaction trans = transactions.poll(); if (buy != null && sell != null && trans != null) { return new Combined(buy, sell, trans); } return null; }) .takeWhile(Objects::nonNull) .collect(Collectors.toCollection(LinkedList::new));
方式3:Java 8兼容版(用limit替代takeWhile)
如果你的项目基于Java 8(不支持takeWhile),可以利用已有的断言(三个队列大小相等),用limit限制流的长度:
import java.util.stream.Collectors; import java.util.stream.Stream; // 直接利用队列大小作为流的长度,无需处理终止条件 Queue<Combined> combined = Stream.generate(() -> new Combined(buys.poll(), sells.poll(), transactions.poll())) .limit(buys.size()) .collect(Collectors.toCollection(LinkedList::new));
方案对比
- 可读性:原循环方式更直观,容易理解;Stream写法更简洁,符合函数式编程风格。
- 性能:两种方式性能几乎无差异,底层都是逐个遍历元素。
- 原队列影响:方式1不会修改原队列,方式2和方式3会通过
poll()清空原队列,和原循环逻辑一致。
内容的提问来源于stack exchange,提问作者limestreetlab
相关产品推荐
相关产品推荐

