Java8 Lambda 性能与公共函数

2023-11-22

我已经使用 Java8 VS 对 lambda 性能进行了演示测试。 Java8 公共函数。

案例如下:

  1. 我有一个现有 10 人的名单(5 男 5 女)。

  2. 我想知道哪位女性的年龄在 18 至 25 岁之间

现在,当我执行这些步骤一百万次时,结果将是:

带有 ForEach 的 Lambda 花费了:395 毫秒(使用 JUnit 为 396 毫秒)

公共函数耗时:173 毫秒(使用 JUnit 为 169 毫秒)

带有 Collect 的 Lambda 花费了:334 毫秒(使用 JUnit 为 335 毫秒)

现在我没想到 lambda 的执行时间比常规函数长两倍到六倍。

所以,现在我很想知道我是否在这里错过了一些东西。

来源可以在这里找到:pastebin.com/BJBk4Tu6


跟进:

  1. 将列表扩展到 1.000.000 项时
  2. 并过滤所有年轻成年女性一次

结果将是:

带有 ForEach 的 Lambda 花费了:59 毫秒

公共函数耗时:15 毫秒

带有 Collect 的 Lambda 花费了:12 毫秒

然而,当我尝试过滤 1000000 人的同一个列表 100 次时,结果将是:

带有 ForEach 的 Lambda 花费了:227 毫秒

公共函数耗时:134 毫秒

带有 Collect 的 Lambda 花费了:172 毫秒

因此,作为最终结论:Lambda 在过滤较大列表时速度更快,而公共函数(旧方法)在过滤较小列表时速度更快。

此外,无论您出于何种目的,多次过滤任何列表时,公共函数都会更快。

最新代码:pastebin.com/LcVhgnYv


正如评论中指出的:您很难从这样一个单一、简单和孤立的微基准测试运行中得出任何结论。

部分引用自另一个(否则不相关的)答案:

为了正确、可靠地测量执行时间,存在多种选择。除了分析器之外,例如VisualVM,有像这样的框架JMH or Caliper,但不可否认,使用它们可能需要一些努力。

For the simplest对于一个非常基本的手动 Java Microbenchmark 形式,您必须考虑以下事项:

  • 多次运行算法,让 JIT 有机会发挥作用
  • 交替运行算法,而不是一个接一个地运行
  • 随着输入大小的增加运行算法
  • 以某种方式保存并打印计算结果,以防止计算被优化掉
  • 考虑一下时间安排may被垃圾收集器 (GC) 扭曲

这些只是经验法则,并且仍然可能会有意想不到的结果(更多详细信息请参阅上面的链接)。但通过这种策略,您通常可以获得有关性能的良好指示,并且至少可以了解是否可能存在really算法之间存在显着差异。

相关阅读:

  • 如何用 Java 编写正确的微基准测试?
  • Java 理论与实践:有缺陷的微基准剖析
  • 热点内部结构

我将这些基本步骤应用到您的程序中。这是一个MCVE :

注意:其余部分已更新以响应问题的后续编辑)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

class Person {
    public static final int MALE = 0;
    public static final int FEMALE = 1;
    private final String name;
    private final int sex;
    private final int age;

    public Person(String name, int sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public int getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }
}

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    private List<Person> people;

    public Main() {

        for (int size=10; size<=1000000; size*=10) {

            Random r = new Random(0);
            people = new ArrayList<Person>();
            for (int i = 0; i < size; i++) {
                int s = r.nextInt(2);
                int a = 25 + r.nextInt(20);
                people.add(new Person("p" + i, s, a));
            }

            int min = 10000000 / size;
            int max = 10 * min;
            for (int n = min; n <= max; n += min) {
                lambdaMethodUsingForEach(n);
                lambdaMethodUsingCollect(n);
                defaultMethod(n);
            }
        }
    }

    public void lambdaMethodUsingForEach(int n) {
        List<Person> lambdaOutput = new ArrayList<Person>();
        long lambdaStart = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            lambdaOutput.addAll(getFemaleYoungAdultsUsingLambdaUsingForEach());
        }
        System.out.printf("List size: %10d, runs: %10d, result: %10d, ForEach took: " +
            (System.currentTimeMillis() - lambdaStart) + " ms\n",
            people.size(), n, lambdaOutput.size());
    }

    public void lambdaMethodUsingCollect(int n) {
        List<Person> lambdaOutput = new ArrayList<Person>();
        long lambdaStart = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            lambdaOutput.addAll(getFemaleYoungAdultsUsingLambdaUsingCollect());
        }
        System.out.printf("List size: %10d, runs: %10d, result: %10d, collect took: " +
            (System.currentTimeMillis() - lambdaStart) + " ms\n",
            people.size(), n, lambdaOutput.size());
    }

    public void defaultMethod(int n) {
        List<Person> defaultOutput = new ArrayList<Person>();
        long defaultStart = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            defaultOutput.addAll(getFemaleYoungAdultsUsingFunctions());
        }
        System.out.printf("List size: %10d, runs: %10d, result: %10d, default took: " +
            (System.currentTimeMillis() - defaultStart) + " ms\n",
            people.size(), n, defaultOutput.size());
    }

    public List<Person> getFemaleYoungAdultsUsingLambdaUsingForEach() {
        List<Person> people = new ArrayList<Person>();
        this.people.stream().filter(
                (p) -> p.getSex() == Person.FEMALE &&
                p.getAge() >= 18 &&
                p.getAge() <= 25).forEach(people::add);
        return people;
    }

    public List<Person> getFemaleYoungAdultsUsingLambdaUsingCollect() {
        return this.people.stream().filter(
                (p) -> p.getSex() == Person.FEMALE &&
                p.getAge() >= 18 &&
                p.getAge() <= 25).collect(Collectors.toList());
    }

    public List<Person> getFemaleYoungAdultsUsingFunctions() {
        List<Person> people = new ArrayList<Person>();
        for (Person p : this.people) {
            if (p.getSex() == Person.FEMALE && p.getAge() >= 18 && p.getAge() <= 25) {
                people.add(p);
            }
        }
        return people;
    }
}

My Machine® 上的输出大致如下:

    ...
List size:       10, runs:   10000000, result:   10000000, ForEach took: 1482 ms
List size:       10, runs:   10000000, result:   10000000, collect took: 2014 ms
List size:       10, runs:   10000000, result:   10000000, default took: 1013 ms
...
List size:      100, runs:    1000000, result:    3000000, ForEach took: 664 ms
List size:      100, runs:    1000000, result:    3000000, collect took: 515 ms
List size:      100, runs:    1000000, result:    3000000, default took: 441 ms
...
List size:     1000, runs:     100000, result:    2300000, ForEach took: 778 ms
List size:     1000, runs:     100000, result:    2300000, collect took: 721 ms
List size:     1000, runs:     100000, result:    2300000, default took: 841 ms
...
List size:    10000, runs:      10000, result:    2450000, ForEach took: 970 ms
List size:    10000, runs:      10000, result:    2450000, collect took: 971 ms
List size:    10000, runs:      10000, result:    2450000, default took: 1119 ms
...
List size:   100000, runs:       1000, result:    2536000, ForEach took: 976 ms
List size:   100000, runs:       1000, result:    2536000, collect took: 1057 ms
List size:   100000, runs:       1000, result:    2536000, default took: 1109 ms
...
List size:  1000000, runs:        100, result:    2488600, ForEach took: 1323 ms
List size:  1000000, runs:        100, result:    2488600, collect took: 1305 ms
List size:  1000000, runs:        100, result:    2488600, default took: 1422 ms

您可以看到两者之间的区别ForEachdefault即使对于较小的列表,(公共方法)方法也正在消失。对于较大的列表,基于 lambda 的方法似乎甚至有一点优势。

再次强调一下:这是一个很简单微基准测试,即使这也不一定能说明这些方法在实践中的性能。然而,至少可以合理地假设ForEach并且公共方法并不像您最初测试建议的那么大。 Nevertleless:对于任何在 JMH 或 Caliper 中运行此程序并发布有关此内容的进一步见解的人,我都会+1。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java8 Lambda 性能与公共函数 的相关文章

  • 运行单个 Java 线程的双核 CPU 利用率[重复]

    这个问题在这里已经有答案了 可能的重复 多线程 Java 应用程序能否很好地利用多核机器 https stackoverflow com questions 1649402 would a multithreaded java applic
  • 为什么 hibernate 在一张表中保存两个 @OneToMany 列表?

    想象一下使用 Hibernate 和 JPA 的简化代码如下 Entity class C Id GeneratedValue public long id MappedSuperclass abstract class A Id Gene
  • JFreeChart - 创建移动图表时出现问题

    我在我的 java 应用程序中使用 JFreeChart Problem 我想绘制一个XY面积图 whose 域轴 x 轴 当我们开始绘制数据时应该自动水平滚动 我在中看到了同样的事情时间序列图表但我不想要任何时间系列图表 我只想要滚动的
  • 到底什么是哈希冲突

    HashMap 中的哈希冲突或哈希冲突并不是一个新主题 我遇到过几个博客和讨论板 以模糊且详细的方式解释如何产生哈希冲突或如何避免它 我最近在一次采访中遇到了这个问题 我有很多事情要解释 但我认为很难准确地给出正确的解释 抱歉 如果我的问题
  • @Cachable 在没有输入参数的方法上?

    我有问题 org springframework cache annotation Cachable注解 Bean public ConcurrentMapCache cache return new ConcurrentMapCache
  • 竞争性编码 - 以最低成本清除所有级别:未通过所有测试用例

    当我遇到这个问题时 我正在一个竞争性编码网站上解决问题 问题指出 游戏中有 N 个关卡和 M 种可用武器 等级编号从 0 到 N 1 武器编号从 0 到 M 1 您可以按任意顺序清除这些级别 在每个关卡中 需要这些 M 武器的某些子集才能通
  • FXML 文件中的 getHostServices().showDocument()

    有没有简单的方法可以将 getHostServices showDocument 命令放入 toHomepage 方法中 而不是执行一行又一行的代码 这样代码应该看起来干净简单 package sample import javafx ap
  • 将 RequestBody json 转换为对象 - Spring Boot

    我是 java 开发的初学者 但之前有 PHP 和 Python 等编程语言的经验 对于如何进行 Spring Boot 的开发几乎没有什么困惑 我正在开发一个rest API 它有以下请求 key value key1 value1 pl
  • 整数与 int 比较

    我是新来的java 我现在正在学习非原始整数类型java 我知道以下比较无效并引发编译错误 String str c Char chr c if str chr return true 上面的代码片段给了我 Test java lineNu
  • 处理 ANTLR 4 中的错误

    遵循后接受的答案 https stackoverflow com a 18137301 2279200的指示处理 ANTLR4 中的错误 https stackoverflow com q 18132078 2279200问题 我遇到了以下
  • 维护插入顺序的并发集合[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个可以维护插入顺序的并发列表 有人有什么好的推荐吗 我看一些番石榴 例如SetFromMa
  • 如何使用键盘上的“删除”按钮作为从 JTable 中删除行的快捷方式[重复]

    这个问题在这里已经有答案了 可能的重复 如何制作删除按钮来删除JTable中的行 https stackoverflow com questions 13236206 how to make delete button to delete
  • Elasticsearch NodeBuilder 与 TransportClient

    对于其他 Elasticsearch 开发人员来说 这可能是一个非常简单 而且愚蠢 的问题 这两者之间有什么区别 我正在从 Java Web 应用程序连接到远程 Elasticsearch 服务器 到目前为止我一直在使用 Transport
  • Java 空值检查

    我有一个thread1 if object null object play 和另一个thread2可以写null into object随时参考 我将同时运行这些线程 我知道thread2可以重写object后参考null检查并会抛出Nu
  • logcat 信息出现在 Android Studio 的“运行”选项卡中

    我的 android studio 运行选项卡很简单 然后它变得更难并给我更多信息 例如 logcat 中的信息 如何禁用或删除第二张图片中出现的更多信息并返回到第一张图片中的第一个外观 我只需要正在运行的 flutter 应用程序的日志输
  • 在 Streamreduce 方法中,求和时恒等式必须始终为 0,乘​​法时恒等式必须始终为 1?

    我继续java 8学习 我发现了一个有趣的行为 让我们看一下代码示例 identity value and accumulator and combiner Integer summaryAge Person getPersons stre
  • 如何从Java中的连接获取查询字符串?

    我正在编写一个方法 尝试记录数据库调用 形成连接到它的连接 在查询之后 有很多地方调用方法 connect 来启动并调用 cleanUp 方法来结束 我不能并且不想修改每个地方 所以顺序是这样的 Connection con connect
  • Java 中 .NET 的 Lambda 表达式

    我最近 再次 从 C 迁移到 Java 但我非常怀念 lambda 表达式和 C 的 IEnumerable Foreach 之类的东西 所以我正在寻找Java中的lambda表达式库 有比这更好的图书馆吗LambdaJ http code
  • Java 应用程序启动,ProcessBuilder 一段时间后被阻止

    我正在开发一个 Java 桌面应用程序 我们称之为控制台 包含 3 个按钮 其中两个启动 Win32 应用程序 第三个应该启动一个可执行的 jar ProcessBuilder pb new ProcessBuilder java jar
  • 在没有 ODBC 的情况下从 Java 操作 Access 数据库

    我想从我的 Java 项目操作 Microsoft Access 数据库 accdb 或 mdb 文件 我不想使用 Microsoft 的 JDBC ODBC Bridge 和 Access ODBC 驱动程序 因为 JDBC ODBC 桥

随机推荐

  • Django 1.3 静态文件放置在应用程序目录中

    我正在使用 Django 1 3 应用程序中的静态文件令人困惑 我在做什么 1 设置 STATIC ROOT as path to directory static in my project STATIC URL static 2 在我的
  • 为什么 bool 到 string 的隐式转换不会出错?

    我用谷歌搜索并试图在 SO 上找到类似的问题 但没有找到任何有用的东西 所以 在这里发布我的问题 考虑这个程序 include
  • 写入文本文件php

    我正在使用 php 我想编写一个 php 页面来从另一个页面获取参数并写入文件文本 和 如果已有文件文本 则写入新行 每天创建一个文件文本 Example 注册 php
  • 如何在C#中获取相对路径中的文件

    如果我有一个名为 app exe 的可执行文件 这是我在 C 中编码的内容 那么如何使用相对路径从与 app exe 加载到同一目录中的文件夹中获取文件 这会引发路径异常中的非法字符 string files Directory GetFi
  • 无法在 Android Studio 3.6 上启用 Gradle 的离线模式

    我正在使用新的Android Studio 3 6 金丝雀 9测试新功能 我无法启用 Gradle 的离线模式 在 Android Studio 首选项窗口的 Gradle 选项卡中 我找不到启用它的入口点 这是一个错误还是 Google
  • Xcode 中多个目标的自动递增构建号

    我的应用程序有 免费 和 付费 版本 并且我想同时自动增加两个版本号 因为有时我使用 免费 版本进行测试 有时我使用 付费 版本进行测试 具体取决于关于我正在做的事情 这些本质上是相同的代码库 我只有两个目标 其中带有用 付费 版本定义的预
  • Linux 中的 SEH 等效项或如何处理操作系统信号(如 SIGSERV)并继续继续

    我目前正在开发一个单元测试框架 用户可以在其中创建测试用例并在框架中注册 我还想确保 如果任何用户测试代码导致崩溃 它不应该使整个框架崩溃 而应该被标记为失败 为了实现这项工作 我编写了以下代码 以便我可以在沙盒功能中运行用户代码 bool
  • Python 使用累加器和任意 lambda 函数进行归约?

    通过累积执行归约的 Pythonic 方式是什么 例如 采取R s Reduce 给定一个列表和任意 lambda 函数 它允许通过设置生成累积结果的向量 而不仅仅是最终结果accumulate T 一个简单的乘法作为 lambda 函数的
  • MongoDB - 唯一索引与复合索引

    假设一个假设文档有 3 个字段 id 对象 ID 电子邮件地址 字符串 帐户 字符串 现在 给定一个对 emailAddress AND account 的查询 以下两个索引中哪一个会表现更好 仅 emailAddress 的唯一索引 假设
  • Storyboard - ViewController 到选项卡栏控制器

    我有视图控制器 它是主界面 包含选项等 我想从第一个视图控制器 gt 选项卡控制器转换 现在 一旦在选项卡控制器中 我想添加更多选项卡 因为默认情况下 xcode 只创建两个选项卡 q 如何在故事板中添加更多选项卡 我将第一个视图控制器嵌入
  • Android WebView里面ListView onclick事件问题

    我有一个 ListView 其中每行都有两个并排的 webview 占据整行 我已经在 ListActivity 中设置了 onListItemClick 但是当我点击其中一行时 它们不会被触发 除非我碰巧点击的地方位于 webview 的
  • findViewById() 可能会产生 NullPointerException

    我接到过很多这样的电话 ListView getView findViewById R id main list view TextView getView findViewById R id items no Android Studio
  • 为什么 Ruby 在 2 个看起来相同的浮点数上无法相等?

    我有一个计算 生成似乎是 Float 22 23 和文字 22 23 如下所示 some object total gt 22 23 some object total class gt Float 22 23 gt 22 23 22 23
  • Oracle - 在动态游标的 LIKE 子句中使用绑定变量

    我正在使用动态游标来获取数据 正在执行的查询类似于 query SELECT column1 column2 FROM my table WHERE column1 LIKE bv1 游标本身是这样执行的 OPEN my cursor FO
  • 如何修改具有复杂嵌套结构的Spark Dataframe?

    我有一个复杂的 DataFrame 结构 并且想轻松地将列清空 我创建了隐式类 可以连接功能并轻松处理 2D DataFrame 结构 但是一旦 DataFrame 使用 ArrayType 或 MapType 变得更加复杂 我就没有太多运
  • C++ 标准:多重集中出现意外的 const_iterator

    我最近遇到了一个奇怪的问题 我会得到一个const iterator而不是预期的iterator当迭代多重集时 事实证明这对 MSVC 来说不是问题 但 g 给了我一个错误 错误 无效的初始化 myPtr 类型的引用来自 const 类型的
  • 如何使用 AutoCompleteTextView 并使用来自 Web API 的数据填充它?

    我想用一个AutoCompleteTextView在我的活动中 并通过查询 Web API 在用户输入时填充数据 我该怎么做呢 我是否创建一个新类并覆盖AutoCompleteTextView performFiltering 或者我是否使
  • 如何使用 AVX2 有效连接两个向量? (VPALIGNR 的车道交叉口版本)

    我已经实现了一个内联函数 mm256 concat epi16 它连接两个包含 16 位值的 AVX2 向量 对于前 8 个数字效果很好 如果我想将它用于向量的其余部分 我应该更改实现 但在我的主程序中使用单个内联函数会更好 问题是 有没有
  • Android 文件名中带空格打不开

    在 SD 卡中打开文件时 我的代码可以正常工作 但是 如果我打开带有空格的文件名 则会发生错误 例如 路径 sdcard download hello hi jpg 我尝试过 string replace 20 它不起作用 try File
  • Java8 Lambda 性能与公共函数

    我已经使用 Java8 VS 对 lambda 性能进行了演示测试 Java8 公共函数 案例如下 我有一个现有 10 人的名单 5 男 5 女 我想知道哪位女性的年龄在 18 至 25 岁之间 现在 当我执行这些步骤一百万次时 结果将是