Reputation: 4454
Let's say we have three methods like these. They all do the same, but how different they are in terms of memory allocation and efficiency? Method one will create instances of Function during each call, but will the second method do the same? Should one always use the third version or either version is safe and the JIT compiler will take care of the memory optimization?
class Test {
Map<String, Set<String>> mapOfSets = new HashMap<>();
static final Function<String, Set<String>> FUNCTION = s -> new HashSet<>();
void method1(String key, String value) {
Function<String, Set<String>> func = s -> new HashSet<>();
mapOfSets.computeIfAbsent(key, func).add(value);
}
void method2(String key, String value) {
mapOfSets.computeIfAbsent(key, s -> new HashSet<>()).add(value);
}
void method3(String key, String value) {
mapOfSets.computeIfAbsent(key, FUNCTION).add(value);
}
}
Upvotes: 5
Views: 4750
Reputation: 719259
There are two ways to answer this:
The Java Language Specification section that describes the evaluation of a lambda expression is written to give compilers / implementations flexibility in whether or not a new object is created. Your question boils down to whether or not the lambda objects are reused ... in the three versions of the code. According to the JLS, the answer is implementation dependent. The only way to be 100% sure is to dump out the native code produced by the JIT compiler1. However according to @Holger's answers to other questions2, current OpenJDK-based Java runtimes do cache and reuse non-capturing lambdas.
Given that the behavior and therefore the performance will depend on the Java implementation, it is debatable whether one should pick one form over the other:
This is a matter of opinion, but my opinion is that the answers to Q1 & Q2 is "No" under most circumstances. Leave it to the JIT compiler to deal with optimization unless profiling tells you that the optimization is significant to your application's overall performance, and your application's overall performance really matters.
1 - See How to see JIT-compiled code in JVM?.
2 - See https://stackoverflow.com/a/27524543/139985 and https://stackoverflow.com/a/23991339/139985.
Upvotes: 5
Reputation: 8529
As comments have mentioned, this can change depending on what Java implementation you use.
For the hotspot jvm (the normal/default java implementation) you can expect all 3 options to be identical in terms of performance. You may think at first that 3 might be better since 1 and 2 might need to create a new Function object each time they are called. However, your assumption that a new object needs to be created each time for method1 (and 2) is false since a non-capturing lambda will be cached at the call site, so the same instance will be reused for each call just like with method3 and you would not see any difference.
this answer is and excellent overview of the topic goes into more detail
So you can use any of the three without worry in this case so use whichever is the most clear for your situation.
Upvotes: 7