Sorting Java Enums

Occasionally when working with JSF I have the need to display the values of a Java Enum in a pick-list.

public enum Cars {
  KIA,
  BMW,
  TOYOTA,
  FERRARI
}

Returning an array of these values is easy enough. Cars.values();

The ordering of the values in the array is set by the ordinal value of the enum, or more simply the order which it appears in the source code. {"KIA", "BMW", "TOYOTA", FERRARI"}

Now depending on your application, if you need to change the order you can simply change the order they appear in the source code. However if you are like me and persisting these values to a database based on their ordinal value to save space then changing the order will break your application.

@NotNull
@Column(columnDefinition = "tinyint")
@Enumerated(EnumType.ORDINAL)
public Cars getCar() {
  return car;
}

public void setEgressCodec(Cars car) {
  this.car = car;
}

The first thing you might want to do is implement Comparable on the Enum and override the compareTo with your own to control the ordering. Unfortunately compareTo() is final on the Enum so we can’t override it.

Here is the solution that I’ve come up with.

First I create a new interface called ComparableEnum

ComparableEnum.java

public interface ComparableEnum {
  public String getDisplayName();
  public int getPriority();
  public boolean isDisplayed();
  public int ordinal();
}

Then I can implement this on my Cars Enum using the cost a car as a value for the priority

Cars.java

public enum Cars implements ComparableEnum {

  KIA("Kia Motors", 15000, true),
  BMW("Bavarian Motor Works", 55000, true),
  TOYOTA("Toyota Motors", 35000, true),
  FERRARI("Ferrari S.p.A.", 150000, true)

  private String displayName;
  private int priority;
  private boolean displayed;

  private Cars(String displayName, int priority, boolean displayed) {
     this.displayName = displayName;
     this.priority = priority;
     this.displayed = displayed;
  }
  public String getDisplayName() {
     return displayName;
  }
  public int getPriority() {
     return priority;
  }
  public boolean isDisplayed() {
     return displayed;
  }
}

Now it’s just a matter adding a couple comparators

EnumNameComparator.java

public class EnumNameComparator<T extends ComparableEnum> implements Comparator<T> {
  public int compare(T o1, T o2)
  {
     if (o1.getDisplayName().compareTo(o2.getDisplayName()) != 0){
        return o1.getDisplayName().compareTo(o2.getDisplayName());
     }
     else if (o1.toString().compareTo(o2.toString()) != 0) {
        return o1.toString().compareTo(o2.toString());
     }
     else {
        return new Integer(o1.ordinal()).compareTo(new Integer(o2.ordinal()));
     }
  }
}

EnumPriorityComparator.java

public class EnumPriorityComparator<T extends ComparableEnum> implements Comparator<T> {
  public int compare(T o1, T o2)
  {
     if (new Integer(o1.getPriority()).compareTo(new Integer(o2.getPriority())) != 0)
     {
        return new Integer(o1.getPriority()).compareTo(new Integer(o2.getPriority()));
     }
     else if (o1.toString().compareTo(o2.toString()) != 0)
     {
        return o1.toString().compareTo(o2.toString());
     }
     else
     {
        return new Integer(o1.ordinal()).compareTo(new Integer(o2.ordinal()));
     }
  }
}

Now I want to be able to sort these easily using any enum I have which implements Comparable enum so I add a generic method.

private static <T extends ComparableEnum> List<T> getEnumSortedByPriority(T[] t) {
  EnumPriorityComparator<T> c = new EnumPriorityComparator<T>();
  List<T> list = removeNonDispalyedValues(t);
  Collections.sort(list, c);
  return list;
}

Now I can create a simple method to return my enum sorted how I wish

public static List<Cars> componentTypes() {
  return getEnumSortedByPriority(ComponentType.values());
}
tags: java
Cody Lerum - May 21, 2010
About outjected.com

Outjected is an infrequent blog about the frequent issues and annoyances that pop up while coding.

These are living posts and will be updated as errors or improvements are found.
About Me
Google+