终止或破坏java 8流循环

vac*_*ach 28 java loops java-8 java-stream

我有一个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
                    }
                });
    }
Run Code Online (Sandbox Code Playgroud)

当满足某些条件时,如何摆脱循环?什么是正确的关闭流的方式?

UPDATE

我误用了流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;
            }
        }
Run Code Online (Sandbox Code Playgroud)

fab*_*ian 35

Stream.forEach不是一个循环,它不是设计用于终止使用类似的东西break.如果流是并行流,则lambda body可以同时在不同的线程上执行(不容易破坏,并且它可能很容易产生不正确的结果).

更好地使用带有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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ yk4ever:告诉这个并行蒸汽吧!例如`IntStream.range(0,1000).boxed().parallel().allMatch(i - > {System.out.println(i); return i%2!= 0;});` (3认同)
  • 你们小小的信仰!你完全可以摆脱lambda循环:`stream.allMatch(value - > {if(...)return true;/*continue*/else return false;/*break*/});` (2认同)

Tia*_*gel 22

嗯,在流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
}
Run Code Online (Sandbox Code Playgroud)

  • 这也是一个选项,但据我所知,抛出和handilng异常在性能方面是太昂贵的操作,应该避免(以及最后提到的块) (5认同)