终止或中断java 8流循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23996454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
terminate or break java 8 stream loop
提问by vach
I have a java 8 stream loop with the following content:
我有一个包含以下内容的 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
}
});
}
How can I break out of loop when some condition is met? Whats the right way to close stream anyway?
满足某些条件时如何跳出循环?无论如何,关闭流的正确方法是什么?
UPDATE
更新
I was misusing streams tecnique assuming that it is a loop, it is not designed for that. Here's the code I've ended up using answer provided below:
我误用了流技术,假设它是一个循环,它不是为此而设计的。这是我最终使用下面提供的答案的代码:
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;
}
}
采纳答案by fabian
Stream.forEachis not a loop and it's not designed for being terminated using something like break. If the stream is a parallel stream the lambda body could be executed on different threads at the same time (not easy to break that and it could easyly produce incorrect results).
Stream.forEach不是循环,也不是为了使用类似的东西终止而设计的break。如果流是并行流,则 lambda 主体可以同时在不同线程上执行(不容易破坏它,并且很容易产生不正确的结果)。
Better use a iterator with a while loop:
最好使用带有 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;
}
}
回答by Tiago Henrique Engel
Well, there is no method to do this in the stream api, (as far as i know).
好吧,在流 api 中没有方法可以做到这一点(据我所知)。
But if you really need it, you can use an Exception.
但是如果你真的需要它,你可以使用异常。
EDIT:For the people giving -1 to this answer I'm not advertising this as an approach one should follow, it's just an option for the cases where you need it, and it does answer the question.
编辑:对于给这个答案给出 -1 的人,我不是在宣传这是一种应该遵循的方法,它只是您需要它的情况下的一种选择,它确实回答了这个问题。
public class BreakException extends RuntimeException {...}
try {
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");
throw new BreakException()
}
});
} catch (BreakException e) {
//Stoped
}

