@Getter
@AllArgsConstructor
public class Bean {
int id;
}
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
long startTime = System.currentTimeMillis();
Method methodGetId = Bean.class.getMethod("getId");
Bean bean = new Bean(33);
int value = (int) methodGetId.invoke(bean);
log.info("java反射获取value:{},耗时{}ms",value,System.currentTimeMillis()-startTime);
startTime = System.currentTimeMillis();
ToIntFunction<Bean> function = Bean::getId;
Bean bean1 = new Bean(33);
int i = function.applyAsInt(bean1);
log.info("Lambda函数获取value:{},耗时{}ms",i,System.currentTimeMillis()-startTime);
}
控制台输出:
对于一次的操作,java反射表现要比Lambda生成函数映射的性能高。
如果将反射invoke操作和lambda生成函数映射执行100_000次呢?
private static final int N = 100_000;
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
long startTime = System.currentTimeMillis();
Bean bean = new Bean(33);
for (int i=0;i<N;i++){
Method methodGetId = Bean.class.getMethod("getId");
methodGetId.invoke(bean);
}
log.info("java反射获取耗时{}ms",System.currentTimeMillis()-startTime);
startTime = System.currentTimeMillis();
Bean bean1 = new Bean(33);
for (int i=0;i<N;i++){
ToIntFunction<Bean> function = Bean::getId;
function.applyAsInt(bean1);
}
log.info("Lambda生成函数映射耗时{}ms",System.currentTimeMillis()-startTime);
}
控制台输出:
处理速度相差约23倍,性能居然提升了这么多。
答案——Lambda 利用 LambdaMetafactory
生成了函数映射代替反射。
生成的函数映射进行函数复用,将一个固定签名的函数缓存起来,下次调用就可以省去函数创建的过程。