e.getId() % 2 == 0).filter(e -> e.getId() > 1000).collect(Collectors.toList());System.out.println(r.size());}static void loopTest。素手烹茶|lambda表达式速度如何呢?看完这篇文章你就明白了( 三 )。" />

素手烹茶|lambda表达式速度如何呢?看完这篇文章你就明白了( 三 )

r = list.stream().filter(e -> e.getName().startsWith("a")).filter(e -> e.getId() % 2 == 0).filter(e -> e.getId() > 1000).collect(Collectors.toList());System.out.println(r.size());}static void loopTest() {List r = new ArrayList<>();for (User user : list) {if (user.getName().startsWith("a")}}System.out.println(r.size());}}这次的测试算是一个比较实际的测试了 , 生成一千万个用户并对其属性进行检查 , 过滤出符合条件的用户 。 测试的数量是一千万 , 但是测试结果相差并不大 。 可见其实lambda表达式并不怎么影响程序的运行速度 。 值得注意的是 , 这个测试数据完全是保存在内存上的 , 而一般情况下数据都是从数据库中加载出来的 。 这时候程序的瓶颈在数据库的IO上 , 就算程序本身速度相差几十毫秒 , 相较于数据库的延迟完全可以忽略不计 。
我们的原则是不进行过早的优化 。 写程序的时候 , 该怎么写就怎么写 , lambda这种好用的新特性 , 该用的时候就应该用 , 不要害怕它影响性能 。 等到程序写完 , 需要优化的时候 , 老老实实的跑profile , 查看程序的瓶颈究竟在哪里 。 一般情况下程序问题都在数据库IO、算法不够高效或者是内存泄露上 , 我还真没听说过哪个程序写的非常完美 , 就是被lambda表达式的速度拖后腿的 。 实际上 , 虽然很多程序员都担心lambda表达式的速度 , 但是他们的程序完全优秀到需要扣lambda表达式细节的这种程度 。
反过来说适当的时候应用这些新特性 , 反而会增加代码的可读性 。 就拿上面这个例子来说 , 通过三次filter方法过滤程序 , 最后用collect方法得到结果 , 这种流式函数调用不仅非常简单易读 , 而且十分优雅 。 反观循环版本中的查找操作 , 只能通过if判断简单粗暴的进行 。 这还是一个简单的例子 , 假如查找操作比较复杂 , 带了十几个查询条件的话 , 那么循环版本的代码就会变成可读性的灾难 。
这里还有一个细节值得注意 。 为了最高效的运行 , 循环版本的代码只能在一个if中不断的增加判断条件 。 而lambda表达式版本则是流式调用了三次filter语句 , 但是它们的运行结果相差不大 。 相信你应该也猜到原因了:lambda表达式和流类库内部做了特殊的优化 , 就算是多个过滤条件 , 也会保证仅仅循环一次 。 因此放心大胆的使用lambda表达式吧!它是编写代码的利器!
lambda表达式 , 更加强大写到这里 , 本文的内容应该是差不多了 。 但是我猜很多朋友看了以后 , 会说“你说了这么多 , lambda表达式不还是比循环慢嘛 。 说来说去 , 我还是要继续用循环” 。 在这里我想说明一下 , 我的观点是:lambda表达式虽然比循环慢那么一点点 , 但是带来的便利性和优化空间 , 远远不是普通循环可以比拟的 。
上面的例子用了一千万次的循环 , 才得到了几十毫秒的差距 。 而实际情况中 , 几千次或者几万次的循环 , 差距便会忽略不计 。 而且如果加上数据库等外部数据源的读写延迟 , 程序的这点运行速度完全就不值一提了 。 所有担心lambda表达式的朋友基本都是杞人忧天 。 而lambda表达式带来的方便确实实实在在的 。 更重要的是 , 普通循环的优化非常困难 , 基本要重写整个代码 , 在这之中很容易发生错误 。 而lambda表达式的优化则简单许多 。
上面的例子恰好是一个适合并行化的例子 , 优化方法很简单 , 多加一行parallel()方法调用即可 。 并行化是另外一个非常复杂的主题 , 但是在这个例子中 , 第一数据量大(一千万之多) , 第二数据易于分割和和合并(ArrayList可以用下标直接定位中间的元素) , 第三操作都是只读的(不会影响到数据集本身) , 所以正好适合并行化 。 并行化之后 , lambda表达式的运行速度已经和循环相差无几了(仅差几毫秒左右) 。 而普通代码的并行化 , 我想这就不是一般程序员可以轻松写出来的东西了 。


推荐阅读