终止或中断java 8流循环[重复]
Posted
技术标签:
【中文标题】终止或中断java 8流循环[重复]【英文标题】:terminate or break java 8 stream loop [duplicate] 【发布时间】:2014-07-22 16:25:23 【问题描述】:我有一个包含以下内容的 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;
【问题讨论】:
这个问题是重复的,但不是很多问题,而是这个问题:***.com/questions/23308193/… 我还没有尝试过,但是...如果您在peek()
消费者中执行您的工作,并在并发安全终止状态对象上使用 anyMatch()
谓词,该怎么办?跨度>
您可以在终端操作前放置sequential()
以避免并发问题。然后只需将forEach
替换为anyMatch
并在谓词return sellOrder.quantity == 0
内返回
【参考方案1】:
Stream.forEach
不是一个循环,也不是为使用break
之类的东西终止而设计的。如果流是并行流,则 lambda 主体可以同时在不同的线程上执行(不容易破坏它,而且很容易产生错误的结果)。
最好使用带有 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;
【讨论】:
谢谢,我好像误用了新功能。 P.S.两者都是同一类型的“订单” 我同意这个答案,除了第一句话。 Stream.forEach 是一个循环。不同之处在于它是内部循环,而不是外部循环。因为循环是内部的,所以不能对其调用 break。 啊,你们这些小信仰!你完全可以摆脱 lambda 循环:stream.allMatch(value -> if (...) return true; /* continue */ else return false; /* break */ );
@yk4ever :告诉平行蒸汽!例如。 IntStream.range(0, 1000).boxed().parallel().allMatch(i -> System.out.println(i); return i % 2 != 0; );
【参考方案2】:
好吧,在流 api 中没有方法可以做到这一点,(据我所知)。
但如果你真的需要它,你可以使用异常。
编辑:对于给这个答案 -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
【讨论】:
这也是一个选项,但据我所知,抛出和处理异常在性能方面过于昂贵,应该避免(以及上面提到的 finally 块) 不适用于并行流。以上是关于终止或中断java 8流循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章
避免( java.nio.file.AccessDeniedException )的 Java 8 Files.walk(..) 终止原因 [重复]