java性能优化lambda_Java8 Lambda性能与公共功能

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

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 people;

public Main() {

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

Random r = new Random(0);

people = new ArrayList();

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 lambdaOutput = new ArrayList();

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 lambdaOutput = new ArrayList();

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 defaultOutput = new ArrayList();

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 getFemaleYoungAdultsUsingLambdaUsingForEach() {

List people = new ArrayList();

this.people.stream().filter(

(p) -> p.getSex() == Person.FEMALE &&

p.getAge() >= 18 &&

p.getAge() <= 25).forEach(people::add);

return people;

}

public List getFemaleYoungAdultsUsingLambdaUsingCollect() {

return this.people.stream().filter(

(p) -> p.getSex() == Person.FEMALE &&

p.getAge() >= 18 &&

p.getAge() <= 25).collect(Collectors.toList());

}

public List getFemaleYoungAdultsUsingFunctions() {

List people = new ArrayList();

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个,并对此发表了一些进一步的见解.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值