Stream流和For循环到底哪个更快

题目:设有一个字符串集合,其中有 N 条数据,请过滤出 1000-2000 之间的数据。

Stream VS For - Round One

假如 N = 10000,使用for循环和stream循序流/并行流分别进行对比:

public static void main(String[] args) {
    // 初始化1万条数据
    ArrayList<String> list = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        list.add(String.valueOf(i));
    }

    // 开启计时器
    StopWatch sw = new StopWatch();
    sw.start("stream-1");
    // 利用skip和limit进行过滤
    list.stream()
            .skip(1000)
            .limit(1001)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-2");
    // 将所有条件写到一个filter中进行过滤
    List<String> collect = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000 && Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-3");
    // 将所有条件分开写到多个filter中进行过滤
    List<String> collect1 = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000)
            .filter(str -> Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("for-1");
     // 使用 for循环+if 进行过滤
    ArrayList<String> strings = new ArrayList<>();
    for (String s : list) {
        if (Integer.parseInt(s) >= 1000 && Integer.parseInt(s) <= 2000) {
            strings.add(s);
        }
    }
    sw.stop();
    System.out.println(sw.prettyPrint());
}

PK 结果(Stream 顺序流):
image.png
PK 结果(Stream 并行流,将stream()方法改为 parallelStream()):
image.png
第一局,For 循环完胜!并且并行流相比顺序流的总耗时要慢。

Stream VS For - Round Two

假如 N = 100000,使用for循环和stream进行对比:

public static void main(String[] args) {
    // 初始化10万条数据
    ArrayList<String> list = new ArrayList<>();
    for (int i = 0; i < 100000; i++) {
        list.add(String.valueOf(i));
    }

    // 开启计时器
    StopWatch sw = new StopWatch();
    sw.start("stream-1");
    // 利用skip和limit进行过滤
    list.stream()
            .skip(1000)
            .limit(1001)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-2");
    // 将所有条件写到一个filter中进行过滤
    List<String> collect = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000 && Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-3");
    // 将所有条件分开写到多个filter中进行过滤
    List<String> collect1 = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000)
            .filter(str -> Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("for-1");
     // 使用 for循环+if 进行过滤
    ArrayList<String> strings = new ArrayList<>();
    for (String s : list) {
        if (Integer.parseInt(s) >= 1000 && Integer.parseInt(s) <= 2000) {
            strings.add(s);
        }
    }
    sw.stop();
    System.out.println(sw.prettyPrint());
}

PK 结果(Stream 顺序流):
image.png
PK 结果(Stream 并行流,将stream()方法改为 parallelStream()):
image.png
第二局,Stream 的skip和limit函数取得胜利!但是在并行流下和for循环旗鼓相当,并且总耗时比顺序流要慢上不少。

Stream VS For - Round Three

假如 N = 1000000,使用for循环和stream进行对比:

public static void main(String[] args) {
    // 初始化100万条数据
    ArrayList<String> list = new ArrayList<>();
    for (int i = 0; i < 100000; i++) {
        list.add(String.valueOf(i));
    }

    // 开启计时器
    StopWatch sw = new StopWatch();
    sw.start("stream-1");
    // 利用skip和limit进行过滤
    list.stream()
            .skip(1000)
            .limit(1001)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-2");
    // 将所有条件写到一个filter中进行过滤
    List<String> collect = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000 && Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("stream-3");
    // 将所有条件分开写到多个filter中进行过滤
    List<String> collect1 = list.stream()
            .filter(str -> Integer.parseInt(str) >= 1000)
            .filter(str -> Integer.parseInt(str) <= 2000)
            .collect(Collectors.toList());
    sw.stop();

    sw.start("for-1");
     // 使用 for循环+if 进行过滤
    ArrayList<String> strings = new ArrayList<>();
    for (String s : list) {
        if (Integer.parseInt(s) >= 1000 && Integer.parseInt(s) <= 2000) {
            strings.add(s);
        }
    }
    sw.stop();
    System.out.println(sw.prettyPrint());
}

PK 结果(Stream 顺序流):
image.png
PK 结果(Stream 并行流,将stream()方法改为 parallelStream()):
image.png
第三局,Stream 的skip和limit 取得胜利!并且在使用并行流的情况下效率得到了显著提升。

总结

注意:下面总结都有一个前提条件,以上 for 循环和 Stream 流中都只是对数据进行了过滤和重新收集,并没有其他操作,比如 IO 或者计算。

  • 1 万数据以内,使用 for 循环的效率明显要比 Stream 流高一些,并且这个数据量不建议使用并行流。
  • 10 万数据左右,使用 Stream 流的效率可能比 for 循环要高一些,取决于使用 Stream 中什么函数,比如专门为求范围提供的 skip、limit 进行范围筛选的效率就要比 filter 的效率更好一些,而将多个条件分开放入 filter 要比将条件一次性写在一个 filter 中效率更好一些。并且这个数据量也不建议使用并行流。
  • 100 万数据左右,使用 Stream 流的效率更好一些,特别是在使用并行流的情况下。

个人理解: 在对于需要处理比较复杂筛选或者计算的场景下,建议使用 Stream 流,它可以提高代码的可读性使代码变得非常的简洁,并且功能非常的丰富可以适应很多场景。在对于数据量小并且筛选条件比较简单的场景下可以使用for循环,毕竟可以比Stream流快上好几毫秒的时间。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值