Подтвердить что ты не робот

Завершить или разбить java 8 stream loop

У меня есть цикл java 8 stream со следующим содержимым:

    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
                    }
                });
    }

Как я могу выйти из цикла, когда выполняется какое-то условие? Каким образом можно все-таки закрыть поток?

ОБНОВЛЕНИЕ

Я неправильно использовал потоки tecnique, полагая, что это цикл, он не предназначен для этого. Вот код, который я получил, используя ответ, приведенный ниже:

        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;
            }
        }
4b9b3361

Ответ 1

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;
    }
}

Ответ 2

Ну, нет способа сделать это в потоке api (насколько я знаю).

Но если вы действительно нуждаетесь в нем, вы можете использовать Exception.

EDIT: Для людей, дающих -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
}