我已经使用 Java8 VS对lambda性能进行了一些演示测试. Java8公共功能.

案例如下:

>我有一个10人(5男5女)的名单.
>我想知道哪个女人的年龄在18到25岁之间

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

Lambda with ForEach took: 395 ms (396 ms using JUnit)

Public functions took: 173 ms (169 ms using JUnit)

Lambda with Collect took: 334 ms (335 ms using JUnit)

现在我没想到lambda的执行时间比普通函数长两倍到六倍.

所以,现在我非常想知道我是否错过了这里的一些东西.

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

跟进:

>将列表扩展为1.000.000项时
>并过滤所有年轻的成年女性一次

结果将是:

Lambda with ForEach took: 59 ms

Public functions took: 15 ms

Lambda with Collect took: 12 ms

但是,当我尝试过滤100,000次现有的1.000.000人时,结果将是:

Lambda with ForEach took: 227 ms

Public functions took: 134 ms

Lambda with Collect took: 172 ms

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

此外,在过滤任何列表时,公共功能更快,无论出于何种目的,您都需要这样做.

最新代码:pastebin.com/LcVhgnYv

解决方法

正如评论中所指出的那样:你很难从这样一个简单而孤立的微基准测试中得出任何结论.

从another (otherwise unrelated) answer部分引用:

In order to properly and reliably measure execution times,there exist several options. Apart from a profiler,like 07001,there are frameworks like 07002 or 07003,but admittedly,using them may be some effort.

For the simplest form of a very basic,manual Java Microbenchmark you have to consider the following:

  • Run the algorithms multiple times,to give the JIT a chance to kick in
  • Run the algorithms alternatingly and not only one after the other
  • Run the algorithms with increasing input size
  • Somehow save and print the results of the computation,to prevent the computation from being optimized away
  • Consider that timings may be distorted by the garbage collector (GC)

These are only rules of thumb,and there may still be unexpected results (refer to the links above for more details). But with this strategy,you usually obtain a good indication about the performance,and at least can see whether it’s likely that there really are significant differences between the algorithms.

Related reading:

  • 07004
  • 07005
  • 07006

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

NOTE: The remaining part was updated in response to the follow-up edit of the question)

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,collect took: " +
            (System.currentTimeMillis() - lambdaStart) + " ms\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,default took: " +
            (System.currentTimeMillis() - defaultStart) + " ms\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;
    }
}

MyMachine®上的输出与此类似:

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

您可以看到ForEach和默认(公共方法)方法之间的差异即使对于较小的列表也会消失.对于较大的列表,基于lambda的方法甚至似乎有一点点优势.

再次强调这一点:这是一个非常简单的微基准测试,即使这并不一定能说明这些方法在实践中的表现.但是,至少可以合理地假设ForEach和公共方法之间的差异不如初始测试所建议的那么大. Nevertleless:对于任何在JMH或Caliper中运行此操作的人来说,我都有1个,并对此发表了一些进一步的见解.

Java8 Lambda性能与公共功能的更多相关文章

  1. ios – 如何使用Magical Record创建和更新对象并保存它们而不使用contextForCurrentThread

    解决方法所以,我使用客观C而不是RubyMotion,但你应该能够这样做:编辑如果要稍后保存上下文,您只需要坚持下去:这里的主要思想是,您只需要掌握上下文并在准备就绪时执行您的操作.如果要进行后台保存,请使用以下方法:

  2. OC的Block、Swift的Closure及C#的Lambda对比

    Block:代码块、语法糖、对象Closure:闭包、自包含模块、捕获前后变量处理逻辑Lambda:可用于创建委托或表达式目录树类型的匿名函数Lambda运算符=>的左边列出了需要的参数,右边定义了赋予Lambda变量方法的实现代码。

  3. Android Studio重构还原所有lambda和其他Java 8功能

    AndroidStudioIDE中是否内置了此类功能?解决方法您可以通过将光标置于–>内来替换lambda.然后按AltEnter然后选择“用……替换lambda”您可以通过展开菜单并选择“修复所有…”来对整个文件执行此操作.您可以按照上述步骤在整个项目中执行此操作,而是单击“运行检查…”选择“整个项目”检查完成后,右键单击“Lambda可以替换…”部分并选择“将lambda替换为……”

  4. android – lambda表达式未使用

    lambda表达式如何未使用?

  5. android – kotlin lambda表达式作为可选参数

    如何将lambda表达式作为Kotlin语言中的可选参数传递我必须传递上面的东西就像可选参数解决方法下面定义了一个接受函数的函数,如果没有提供函数,则指定传递函数的默认值.您可以传递自己的功能:您可以省略该功能并使用默认值:或者,您可以将标准库maxOf函数作为默认值,而不是编写自己的函数:

  6. Python lambda 匿名函数优点和局限性深度总结

    这篇文章主要为大家介绍了Python lambda 匿名函数的优点和局限性深度总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  7. 深入了解Python中Lambda函数的用法

    lambda函数是Python中常用的内置函数,又称为匿名函数。和普通函数相比,它只有函数体,省略了def和return,使得结构看起来更精简。本文将详细说说Lambda函数的用法,需要的可以参考一下

  8. Lambda表达式的使用及注意事项

    这篇文章主要介绍了Lambda表达式的使用及注意事项,主要围绕 Lambda表达式的省略模式 Lambda表达式和匿名内部类的区别的相关内容展开详情,感兴趣的小伙伴可以参考一下

  9. Java中的lambda和stream实现排序

    这篇文章主要介绍了Java中的lambda和stream实现排序,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

  10. python函数和python匿名函数lambda详解

    这篇文章主要介绍了python函数和python匿名函数lambda,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部