我有一个Java 8流循环,其内容如下:
void matchSellOrder(Market market, Order sellOrder) { System.out.println("selling " + market.pair() + " : " + sellOrder); market.buyOrders() .stream() .filter(buyOrder -> buyOrder.price >= sellOrder.price) .sorted(BY_ASCENDING_PRICE) .forEach((buyOrder) -> { double tradeVolume = Math.min(buyOrder.quantity, sellOrder.quantity); double price = buyOrder.price; buyOrder.quantity -= tradeVolume; sellOrder.quantity -= tradeVolume; Trade trade = new Trade.Builder(market, price, tradeVolume, Trade.Type.SELL).build(); CommonUtil.convertToJSON(trade); if (sellOrder.quantity == 0) { System.out.println("order fulfilled"); // break loop there } }); }
满足某些条件时如何跳出循环?什么是关闭流的正确方法呢?
更新
我滥用流技术,假设它是一个循环,不是为此而设计的。这是我使用下面提供的答案最终得到的代码:
List<Order> applicableSortedBuyOrders = market.buyOrders() .stream() .filter(buyOrder -> buyOrder.price >= sellOrder.price) .sorted(BY_ASCENDING_PRICE) .collect(toList()); for(Order buyOrder : applicableSortedBuyOrders){ double tradeVolume = Math.min(buyOrder.quantity, sellOrder.quantity); double price = buyOrder.price; buyOrder.quantity -= tradeVolume; sellOrder.quantity -= tradeVolume; Trade trade = new Trade.Builder(market, price, tradeVolume, Trade.Type.SELL).build(); CommonUtil.printAsJSON(trade); if (sellOrder.quantity == 0) { System.out.println("order fulfilled"); break; } }
Stream.forEach不是循环,也并非设计为使用终止break。如果流是并行流,则lambda主体可以同时在不同的线程上执行(这不容易打破,并且很容易产生错误的结果)。
Stream.forEach
break
最好使用带有while循环的迭代器:
Iterator<BuyOrderType> iter = market.buyOrders() // replace BuyOrderType with correct type here .stream() .filter(buyOrder -> buyOrder.price >= sellOrder.price) .sorted(BY_ASCENDING_PRICE).iterator(); while (iter.hasNext()) { BuyOrderType buyOrder = iter.next() // replace BuyOrderType with correct type here double tradeVolume = Math.min(buyOrder.quantity, sellOrder.quantity); double price = buyOrder.price; buyOrder.quantity -= tradeVolume; sellOrder.quantity -= tradeVolume; Trade trade = new Trade.Builder(market, price, tradeVolume, Trade.Type.SELL).build(); CommonUtil.convertToJSON(trade); if (sellOrder.quantity == 0) { System.out.println("order fulfilled"); break; } }