如何终止或中断 Java 8 流循环

已解决 javastream
1

我有一个 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
                }
            });
}

当满足某种条件时,怎样才能跳出循环?关闭 Stream 的正确方法是什么?

如果觉得这对你有用,请随意赞赏,给与作者支持
回答 (2)
2 个回答

0

在 Java8 中遇到这种问题,一般我的处理方式是仍然用传统的 foreach 来做,不使用 lambda。

上面的方法虽然可行,但是还是绕了一大圈,并且还是做了很多多余的事情,把应该 break 之后的元素也做了处理,考虑有元素 10000,并且正常在第 10 个元素的时候就应该终止掉,那么后面相当于在对 9990 个元素做无用功。

并且 Stream.forEach lambda 中 break 的作用相当于传统 foreach 中的 continue

0

已采纳

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

根据这种方法,问题里的代码可以这样来写:

void matchSellOrder(Market market, Order sellOrder) {
    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;
        }
    }
}