Java8 Stream性能如何及评测工具推荐

简介: Java8 Stream性能如何及评测工具推荐

作为技术人员,学习新知识是基本功课。有些知识是不得不学,有些知识是学了之后如虎添翼,Java8的Stream就是兼具两者的知识。不学看不懂,学了写起代码来如虎添翼。

在上篇《Java8 Stream新特性详解及实战》中我们介绍了Java8 Stream的基本使用方法,尝试一下是不是感觉很爽?当只用一行代码就搞定最终结果时,是不是再也不想用for循环一遍遍去迭代了。

同时,你是否又看到类似《Java8 Lambda表达式和流操作如何让你的代码变慢5倍》这样的文章,那么今天就带大家通过编写测试程序来一探究竟,看看Stream的性能到底如何。同时,带大家认识一个非常不错的性能测试工具junitperf。

测试环境

先同步一下测试环境及工具信息:

  • JDK版本:1.8.0_151。
  • 电脑配置:MacBook Pro i7,16G内存。
  • Java测试工具:junitperf及Junit。
  • IDE:intellij IDEA。


在测试的过程中电脑中还开了其他很多应用,但基本上都没进行操作。

实验一:基本类型迭代

基本测试方案,先初始化一个int数组,5亿个随机数。然后从这个数组中找到最小的一个数。

采用三个单元测试方法来对照参考:

  • testIntFor方法测试for循环执行时间;
  • testIntStream方法测试串行Stream执行时间;
  • testIntParallelStream方法测试并行Stream执行时间;


测试程序相关代码:



















































public class StreamTest {
  public static int[] arr;
  @BeforeAll  public static void init() {    arr = new int[500000000];    randomInt(arr);  }
  @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})  public void testIntFor() {    minIntFor(arr);  }
  @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})  public void testIntParallelStream() {    minIntParallelStream(arr);  }
  @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})  public void testIntStream() {    minIntStream(arr);  }
  private int minIntStream(int[] arr) {    return Arrays.stream(arr).min().getAsInt();  }
  private int minIntParallelStream(int[] arr) {    return Arrays.stream(arr).parallel().min().getAsInt();  }
  private int minIntFor(int[] arr) {    int min = Integer.MAX_VALUE;    for (int anArr : arr) {      if (anArr < min) {        min = anArr;      }    }    return min;  }
  private static void randomInt(int[] arr) {    Random r = new Random();    for (int i = 0; i < arr.length; i++) {      arr[i] = r.nextInt();    }  }}

基本操作流程:通过@BeforeAll注解的init方法对数组进行随机初始化,然后再统一执行上面三个方法。

在单元测试的方法上都有下面的注解:


@JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})

该注释为junitperf提供的注解,其中duration为持续执行这段代码的时间,单位毫秒;warmUp预热时间,这里预热1秒;reporter输出报表格式,这里采用HTML展示,可以更直观看到效果。

好上面的一切都准备好了,剩下的就是统一执行单元测试。执行结果如下三个图。

image.pngimage.pngimage.png针对基础类型(int)操作,结果分析:

  • 串行Stream的执行的确不如for循环性能高,耗时大概是for循环的2倍。
  • 并行Stream的执行性能要优于for循环,耗时大概是for循环的一半。
  • 这里没有用不同核数的机器测试,但并行Stream随着服务器核数的增加,必然更快。

实验二:对象迭代

生成一个List列表,列表中随机生成1千万个字符串,然后分别通过不同的方式计算获得最小的字符串。基本操作与实验一相同,不再贴出代码,直接看测试的效果图。image.pngimage.pngimage.png针对对象(String)操作,结果分析:

  • Stream的性能与for循环已经相差不大了,耗时大概是for循环的1.25倍左右。
  • 并行Stream执行的性能要优于for循环,而且比基础类型的优势更高,耗时已经低于for循环的一半。
  • 针对不同服务器核数,Stream效率同样会更加高。

实验三:复杂对象归约

生成一个List列表,列表里面存放着1百万个User对象。每个对象中都包含用户名和用户某次运动的距离,同一用户可在List里包含多条运动记录。现在通过不同的方式来统计用户的总共运动了多远距离。

基本测试思路一致,这里只贴出基于Stream的算法的代码,以便大家了解Stream的复杂对象归约如何使用。









// 串行写法users.stream().collect(        Collectors.groupingBy(User::getUserName,            Collectors.summingDouble(User::getMeters)));// 并行写法            users.parallelStream().collect(        Collectors.groupingBy(User::getUserName,            Collectors.summingDouble(User::getMeters)));

下面看测试结果的数据:

image.pngimage.pngimage.png复杂对象归约操作,结果分析:

  • 基于Stream的操作明显都高于for循环的效率,而且并行的效果更加明显。
  • 同样,随着服务器核数的增加,并行Stream的效率会更高。


最后推荐一下这款用起来还不错的Java性能测试工具,GitHub地址:https://github.com/houbb/junitperf 上面有详细的使用说明。唯一缺少的就是数据预初始化的示例,而本篇文章的示例中已经补上了这部分缺失。

小结

通过上面的几组实验对比,我们可以看到如下结论:

  • 针对简单的操作,比如基础类型的遍历,使用for循环性能要明显高于串行Stream操作。但Stream的并行操作随着服务器的核数增加,会优于for循环。
  • 针对复杂操作,串行Stream性能与for循环不差上下,但并行Stream的性能已经是无法匹敌了。
  • 特别是针对一个集合进行多层过滤并归约操作,无论从写法上或性能上都要明显优于for循环。


用一句话来说就是:简单操作for循环即可,复杂操作首推Stream

现在的Stream书写简单,性能不错,如果未来JDK针对其进行优化,便同时享受了便捷和性能,何乐而不为呢。


目录
相关文章
|
20天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
1月前
|
Java
java中日期处理的一些工具方法
java中日期处理的一些工具方法
17 1
|
27天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
17 4
|
7天前
|
存储 安全 Java
说说Java 8 引入的Stream API
说说Java 8 引入的Stream API
9 0
|
7天前
|
SQL 缓存 Java
Java数据库连接池:优化数据库访问性能
【4月更文挑战第16天】本文探讨了Java数据库连接池的重要性和优势,它能减少延迟、提高效率并增强系统的可伸缩性和稳定性。通过选择如Apache DBCP、C3P0或HikariCP等连接池技术,并进行正确配置和集成,开发者可以优化数据库访问性能。此外,批处理、缓存、索引优化和SQL调整也是提升性能的有效手段。掌握数据库连接池的使用是优化Java企业级应用的关键。
|
7天前
|
分布式计算 Java API
Java 8新特性之Lambda表达式与Stream API
【4月更文挑战第16天】本文将介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁、易读。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而使代码更加简洁、高效。本文将通过实例代码详细讲解这两个新特性的使用方法和优势。
|
11天前
|
存储 Java 测试技术
Java 21革命性升级:探索分代ZGC的性能奇迹
Java 21革命性升级:探索分代ZGC的性能奇迹
13 0
|
11天前
|
前端开发 Oracle Java
Java 22 新增利器: 使用 Java Stream Gather 优雅地处理流中的状态
Java 22 新增利器: 使用 Java Stream Gather 优雅地处理流中的状态
22 0
|
11天前
|
存储 Java 关系型数据库
掌握Java 8 Stream API的艺术:详解流式编程(一)
掌握Java 8 Stream API的艺术:详解流式编程
42 1
|
14天前
|
存储 Java API
java8新特性 lambda表达式、Stream、Optional
java8新特性 lambda表达式、Stream、Optional

热门文章

最新文章