J'ai une boucle de flux Java 8 avec le contenu suivant:
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
}
});
}
Comment puis-je sortir de la boucle quand une condition est remplie? Quelle est la bonne façon de fermer le flux de toute façon?
MISE À JOUR
J'utilisais mal les streams techniques en supposant que c'est une boucle, elle n'est pas conçue pour ça. Voici le code que j'ai fini par utiliser la réponse fournie ci-dessous:
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
n'est pas une boucle et n'est pas conçu pour être terminé à l'aide de quelque chose comme break
. Si le flux est un flux parallèle, le corps lambda pourrait être exécuté sur différents threads en même temps (pas facile à casser et cela pourrait facilement produire des résultats incorrects).
Mieux vaut utiliser un itérateur avec une boucle 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;
}
}
Eh bien, il n'y a pas de méthode pour le faire dans l'API Stream (pour autant que je sache).
Mais si vous en avez vraiment besoin, vous pouvez utiliser une exception.
EDIT: Pour les personnes donnant -1 à cette réponse, je ne fais pas de publicité comme approche, c'est juste une option pour les cas où vous en avez besoin, et cela répond à la question.
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
}