dmitryvinn dmitryvinn - 9 months ago 28
Java Question

Comparator as an anonymous sorter in a stream

Let's say I am trying to sort a collection with a specific Comparator. Does it matter from a performance point of view to have a comparator defined in the sorted() clause of as a an anonumous instance, or it is better to create an instance once and just call compare method in the sorted() clause?

In essence, what is better:

    new Comparator<String>(){
    public int compare(String a, String b){

  2. Comparator<String> comp = new MyCustomComparator<>();

Note: neither syntax, nor comparing values matter - I want to know conceptually whether JVM is smart enough to initialize my anonymous comparator only once (case 1) and keep reusing just one method, or it will keep creating new instances (then I would choose case 2)


A new instance of an anonymous class will be created every time the expression using new is evaluated.

  • In your first example, a new one is created every time the statement runs where you are passing it to sorted.

  • In your second example, a new one is created wherever the comp variable is being initialized. If comp is an instance member, then it gets created whenever the object that owns it is created. If comp is a local variable in a method, then it gets created every time the method is called.

A static, stateless and non-capturing Comparator is always going to be the most efficient way, because you can create it once and keep it forever. (See for example String.CASE_INSENSITIVE_ORDER.)

That's not to say you shouldn't use another way.

In Java 8, you should prefer lambdas over anonymous classes. Non-capturing lambdas can be cached and only created once. For example, this program outputs true:

class Example {
    public static void main(String[] args) {
        System.out.println(comparator() == comparator());

    static Comparator<String> comparator() {
        return (lhs, rhs) -> lhs.compareTo(rhs);

(Example on Ideone.)

All that said, you shouldn't worry about creating a few small objects here in there in Java, because it's unavoidable and the garbage collector is optimized for it. The vast majority of the time, the "best" way to do something is also the most readable.

Note that you do not have to use a method reference in your second example. You can pass it to the method directly:

Comparator<String> comp = new MyCustomComparator<>();