There will be a difference.
- CPU Impact: Assigning to a static one reduces the amount of work needed to distribute a new comparator each time
- GC effect: each time assigning a new object, and then immediately discarding it, it will not have any young GC value; however, assigning it to a variable will increase GC times (very very slightly), since this is an additional set of links that you will need to go through. Dead objects cost nothing, living objects do.
- Memory effect: assigning a comparator constant will reduce the amount of memory that each method call will need, in exchange for low constant overheads that will be moved to a space with a limited amount of GC.
- Risk of reference screens: Inner classes contain pointers to the class that built it. If the inner class (Comparator) ever came back from the method that created it, then a strong reference to the parent could avoid and prevent the parent's GC. Purely getcha, which can creep into code, in this example this is not a problem.
An access point is very good for inlining, but it is unlikely that the comparator can be allocated on the heap or moved to a constant. But this will depend on the contents of the TreeSet. If the implementation of TreeSet was very simple (and small), then it could be embedded, however we all know that this is not so. Also, the TreeSet is encoded as general if it was used with only one type of object (Worker), then there are some optimizations that the JVM can use, however, we must assume that the TreeSet will also be used by other types, and therefore the TreeSet will not be able to do any suggestion that the comparator is in it.
Thus, the difference between the two versions is mainly in the distribution of objects. Using the final keyword is unlikely to improve performance, since Hotspot basically ignores the last keyword.
Java 8 has a very interesting behavior when using lambdas. Consider the following version of your example:
import java.util.*; public class T { public void iterate(List<String> workers) { SortedSet<Double> set = new TreeSet<>( Double::compare ); } }
Run 'javap -c T.class' and you will see the following jvm code:
public void iterate(java.util.List<java.lang.String>); Code: 0: new #2
It is great to note here that there is no object construction for lambda. invokedynamic will have a higher cost on the first call, and then it will be cached efficiently.
source share