java forEach 如何跳出循环 如何使用 continue break,stream parallel 效率

java forEach 如何跳出循环?如何使用 continue break?stream parallel效率如何?

我答: 不需要在使用forEach的时候跳出循环,可以使用stream,forEach等专门针对集合的工具来做遍历操作,完全代替关键字for,break,continue;效率见下文。

我的理由

如果你使用forEach,那你一定知道lambda表达式,如果你知道lambda表达式,那你大概率会用stream,使用stream可以不需要break和continue。

想使用break的场景

无非是一个list里面,要对id=xx的进行操作,这个时候可以用stream的filter,直接筛选出这个就可以了,如果id=xx的有多个,你只要任意一个,那么可以使用findFirst

MyObject  myObject = list.stream.filter(s -> {xx}).findFirst().orElse(null);

想使用continue的场景

continue是可以通过调整逻辑代码给去掉的

if(type == 2) {
	fieldValueA += 10;
	continue;
} else if(type == 3) {
	fieldValueA += 15;
} else {
	fieldValueA = 0;
}
fieldB += 20;

// 可以替换为
if(type == 2) {
	fieldValueA += 10;
} else if(type == 3) {
	fieldValueA += 15;
} else {
	fieldValueA = 0;
}
if(type != 2) {
	fieldB += 20;
}

关于效率

在一个循环里统计三个字段的和,写成stream的话会有三个stream。stream可以把一次连续调用里的操作优化到一个循环里(这个是我看stream效率博客看的,好像是这样,嗯,大概),但是没法把分开写的三次stream优化到同一个循环里,那写三个stream的时间复杂度不就是普通的for的3倍?

试一下

	@Test
    public void streamTest() {
        streamTestWithCycleNum(10000); // 万
        streamTestWithCycleNum(100000); // 十万
        streamTestWithCycleNum(1000000); // 百万
        streamTestWithCycleNum(10000000); // 千万
        streamTestWithCycleNum(100000000); // 亿
    }

    private void streamTestWithCycleNum(int cycleNum) {
        System.out.println("循环次数:" + cycleNum);
        HpBillAllocation hpBillAllocation = new HpBillAllocation();
        hpBillAllocation.setOrderMoney(BigDecimal.valueOf(156));
        hpBillAllocation.setChargeAmount(BigDecimal.valueOf(415));
        hpBillAllocation.setPaidAmount(BigDecimal.valueOf(786));
        hpBillAllocation.setActivityAmount(BigDecimal.valueOf(119));
        List<HpBillAllocation> hpBillAllocations = new ArrayList<>();
        for (int i = 0; i < cycleNum; i++) {
            hpBillAllocations.add(hpBillAllocation);
        }
        long forBeginTime = System.nanoTime();
        BigDecimal totalAmount = new BigDecimal(0);
        BigDecimal successAmount = new BigDecimal(0);
        BigDecimal refundAmount = new BigDecimal(0);
        int successCount = 0;
        int refundCount = 0;
        for (HpBillAllocation billAllocation : hpBillAllocations) {
            BigDecimal chMoney = billAllocation.getOrderMoney();
            totalAmount = totalAmount.add(chMoney);
            if (chMoney.compareTo(BigDecimal.ZERO) >= 0) {
                hpBillAllocation.setChOrderType(WXPayConstants.CH_ORDER_TYPE_PAY);
                successAmount = successAmount.add(chMoney);
                successCount += 1;
            } else {
                hpBillAllocation.setChOrderType(WXPayConstants.CH_ORDER_TYPE_REFUND);
                refundAmount = refundAmount.add(chMoney);
                refundCount += 1;
            }
        }
        long forEndTime = System.nanoTime();
        System.out.println("forTime: " + (forEndTime - forBeginTime)/1000000 + "ms");

        long streamBeginTime = System.nanoTime();
        HpBillAllocation hpBillAllocation1 = hpBillAllocations.stream().findFirst().orElse(null);
        totalAmount = BigDecimal.valueOf(hpBillAllocations.stream().mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successAmount = BigDecimal.valueOf(hpBillAllocations.stream().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) >= 0).mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successCount = (int)hpBillAllocations.stream().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) >= 0).count();
        refundAmount = BigDecimal.valueOf(hpBillAllocations.stream().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) < 0).mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successCount = (int)hpBillAllocations.stream().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) < 0).count();
        long streamEndTime = System.nanoTime();
        System.out.println("streamTime: " + (streamEndTime - streamBeginTime)/1000000 + "ms");

        long streamParallelBeginTime = System.nanoTime();
        totalAmount = BigDecimal.valueOf(hpBillAllocations.stream().parallel().mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successAmount = BigDecimal.valueOf(hpBillAllocations.stream().parallel().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) >= 0).mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successCount = (int)hpBillAllocations.stream().parallel().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) >= 0).count();
        refundAmount = BigDecimal.valueOf(hpBillAllocations.stream().parallel().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) < 0).mapToLong(s -> s.getOrderMoney().longValue()).sum());
        successCount = (int)hpBillAllocations.stream().parallel().filter(s -> s.getOrderMoney().compareTo(BigDecimal.ZERO) < 0).count();
        long streamParallelEndTime = System.nanoTime();
        System.out.println("streamParallelTime: " + (streamParallelEndTime - streamParallelBeginTime)/1000000 + "ms\n");
    }

输出

循环次数:10000
forTime: 1ms
streamTime: 28ms
streamParallelTime: 7ms

循环次数:100000
forTime: 7ms
streamTime: 4ms
streamParallelTime: 15ms

循环次数:1000000
forTime: 24ms
streamTime: 28ms
streamParallelTime: 3ms

循环次数:10000000
forTime: 257ms
streamTime: 250ms
streamParallelTime: 32ms

循环次数:100000000
forTime: 9625ms
streamTime: 2428ms
streamParallelTime: 313ms

虽然不知道原理,但是可以看到,数据量越大,for效率越赶不上stream,即使是没有使用parallel的情况下。这个情况跟cpu效率有关,我对比了别人的博客,cpu越差,用stream效率越早反超

关于stream的一些技巧

可能会觉得stream api有点多,自己要学习有点麻烦,其实根本不需要,或者说只用学习一点点。
2023了,ai在语言方面的能力可能会超乎一些人的想象,有梯子,可以直接使用免费的new bing,
没有梯子也没关系,我们可以使用百度ai,不过就我使用经验来看百度的生成的东西有时候是错的,没new bing好用,不过大部分时间也够用了,出来的代码总归要自己检查一下的,直接上图。

new bing

在这里插入图片描在这里插入图片描述
述
在这里插入图片描述

百度ai

在这里插入图片描述
在这里插入图片描述
对于统计bigdecimal的和,bing的BigDecimal:ZERO在reduce方法里的,针对空值的时候就取0,百度这个丢到后面的在编译器里报错了,即使是对的也没有bing的写法优雅。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java中,使用foreach循环无法直接使用关键字breakcontinue跳出循环。如果在foreach循环体内使用这些关键字,会导致编译错误,报错信息为"break outside switch or loop"或"continue outside of loop"。\[1\] 如果需要在foreach循环中跳出循环,可以使用Java 8的Stream API来实现。通过在循环体内抛出RuntimeException异常来终止循环。例如: ```java colls.stream().forEach(item -> { if (item == 5) { throw new RuntimeException("通过抛出异常,终止for循环"); } System.out.println("Stream 当前item 值为:" + item); }); ``` 这样可以在满足某个条件时,抛出异常来终止循环。\[2\] 另外,如果使用传统的for循环,可以使用关键字continue来跳过当前循环,继续下一轮循环;使用关键字break来结束循环。例如: ```java int\[\] intArr = new int\[\]{1,2,3,4,5,6,7,8,9,10}; StringBuilder content = new StringBuilder(16); for (int i = 0; i < intArr.length; i++) { int item = intArr\[i\]; //跳过本次循环,继续下一轮循环 if(item == 5){ continue; } //结束循环 if(item == 8){ break; } content.append(item); } ``` 在这个例子中,当item等于5时,使用continue关键字跳过本次循环,继续下一轮循环;当item等于8时,使用break关键字结束循环。\[3\] #### 引用[.reference_title] - *1* *3* [JAVA8跳出循环-forEach实现continuebreak效果](https://blog.csdn.net/u014133299/article/details/122862734)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Java 跳出For循环总结](https://blog.csdn.net/zhouzhiwengang/article/details/128655093)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值