1

Suppose I have a Record class with a String name (could be any other type) attribute. In another class I have a method order(List<Record>) which needs to sort the list by name. To do this, I want to create a custom stateless Comparator. I have seen three options that are commonly used:

  1. Static comparator

    private static final Comparator<Record> STATIC_COMPARATOR = new StaticComparator();
    private static class StaticComparator implements Comparator<Record> {
        @Override
        public int compare(Record m1, Record m2) {
            return m1.getName().compareTo(m2.getName());
        }
    }
    
    void order(List<Record> records) {
        records.sort(STATIC_COMPARATOR);
    }
    
  2. Singleton comparator

    private static enum SingletonComparator implements Comparator<Record> {
        INSTANCE;
    
        @Override
        public int compare(Record m1, Record m2) {
            return m1.getName().compareTo(m2.getName());
        }
    }
    
    void order(List<Record> records) {
        records.sort(SingletonComparator.INSTANCE);
    }
    
  3. Use Comparator.comparing()

    void order(List<Record> records) {
        records.sort(Comparator.comparing(Record::getName));
    }
    

Assuming order() gets called a lot, what are the tradeoffs for each approach? How do they compare on matters such as serialization, thread safety, and performance?

Anderson Vieira
  • 8,919
  • 2
  • 37
  • 48
  • 1 and 2 are the same. 3 is the same (except creates a new `Comparator` instance) if the JVM you use implements method references by returning the same instance. – Sotirios Delimanolis Apr 09 '15 at 18:52
  • The main difference between 1 and 2 is the thread safety in creation of the instance. For the comparators you post, however, this is probably irrelevant. – Andy Turner Apr 09 '15 at 18:53
  • @AndyTurner I don't think so. `static` initializer runs behind a lock. The code generated for the `enum` is equivalent. – Sotirios Delimanolis Apr 09 '15 at 18:54
  • @sotiros yeah, you are right. – Andy Turner Apr 09 '15 at 18:57
  • Your comparator is stateless, so serialization and thread safety are non-issues. As for performance, you're probably talking nanosecond difference. Even with millions of comparisons. – ControlAltDel Apr 09 '15 at 19:00
  • @ControlAltDel Couldn't performance be a problem in the third case, when using `Comparator.comparing()`? – Anderson Vieira Apr 09 '15 at 19:02
  • @SotiriosDelimanolis Do you know if the HotSpot or the OpenJDK implement method references by returning the same instance? Is there a name for this feature? – Anderson Vieira Apr 09 '15 at 19:11
  • I'd like to suggest that you make your Record class implement a `Comparable` interface and then override the `compareTo()` method instead. That way, you can sort your List with ease. Would this be an option for you, or do you really want to stick to using `Comparator`s? – theguywhodreams Apr 09 '15 at 19:13
  • See http://stackoverflow.com/questions/27524445/does-a-lambda-expression-create-an-object-on-the-heap-every-time-its-executed/27524543#27524543 – Sotirios Delimanolis Apr 09 '15 at 19:15
  • @theguywhodreams Thanks. But the `Record` class is just an example. Implementing `Comparable` is not a good option in my real problem. – Anderson Vieira Apr 09 '15 at 19:16

0 Answers0