Batakj
Batakj

Reputation: 12743

How to sort a List<Enum, Collection> by order of an enum?

Enum:

 public enum ComponentType {
    INSTRUCTION, ACTION, SERVICE, DOMAIN, INTEGRATION,  OTHER, CONTEXT;
 }

Class A :

 public class A
 {
    String name;
    ComponentType c;
    public A(String name, ComponentType c)
    {
      this.name = name;
      this.c = c;
    }

 }   

Code:

 List<A> l = new ArrayList<A>();
 l.add(new A("ZY", ACTION));  
 l.add(new A("ZY0", INSTRUCTION));  
 l.add(new A("ZY1", DOMAIN));  
 l.add(new A("ZY2", SERVICE));  
 l.add(new A("ZY3", INSTRUCTION));  
 l.add(new A("ZY4", ACTION));  

How to sort list according to enum order?

Upvotes: 8

Views: 18674

Answers (10)

Costi Ciudatu
Costi Ciudatu

Reputation: 38195

You should simply delegate to the enum compareTo method which is already provided and reflects the declaration order (based on the ordinal value):

Collections.sort(list, (a1, a2) -> a1.getType().compareTo(a2.getType()));        

Or, if you think that the component type provides the "natural order" for your elements, you can make the A class itself implement Comparable and also delegate the compareTo method to the ComponentType one.

Upvotes: 7

AppiDevo
AppiDevo

Reputation: 3225

I had the same problem but I couldn't modified my Enum class and the order was wrong. That's why I couldn't use simple compareTo on enum object. The solution is very simple, just assign the int value for every Enum field and then compare it:

public class MyComparator implements Comparator<A> {

    @Override
    public int compare(A o1, A o2) {
        return Integer.compare(getAssignedValue(o1.getComponentType()), getAssignedValue(o2.getComponentType()));
    }

    int getAssignedValue(ComponentType componentType) {
        switch (componentType) {
            case OTHER:
                return 0;
            case CONTEXT:
                return 1;
            case SERVICE:
                return 2;
            case DOMAIN:
                return 3;
            case INTEGRATION:
                return 4;
            case ACTION:
                return 5;
            case INSTRUCTION:
                return 6;
            default:
                return Integer.MAX_VALUE;

        }
    }

}

And then:

Collections.sort(list, new MyComparator);

Upvotes: 3

Peter Lawrey
Peter Lawrey

Reputation: 533530

It appears you should be using an EnumMap as they are naturally sorted by the key.

public static void add(Map<ComponentType, List<A>> map, A a) {
    List<A> as = map.get(a.c);
    if(as == null) map.put(a.c, as = new ArrayList<A>());
    as.add(a);
}

Map<ComponentType, List<A>> map = new EnumMap<ComponentType, List<A>>(ComponentType.class);
add(map, new A("ZY", ComponentType.ACTION));
add(map, new A("ZY0", ComponentType.INSTRUCTION));
add(map, new A("ZY1", ComponentType.DOMAIN));
add(map, new A("ZY2", ComponentType.SERVICE));
add(map, new A("ZY3", ComponentType.INSTRUCTION));
add(map, new A("ZY4", ComponentType.ACTION));

Upvotes: 1

Vishal
Vishal

Reputation: 3279

If it is required to sort the class based on ENUM, for consistency purpose we must use the ENUM's compareTo(which if final) method.

Adding this method to A class will help and keep the consistent behaviour.

@Override
public int compareTo(A o) {
    return this.c.compareTo(o.c);
}

Upvotes: 1

Petr Mensik
Petr Mensik

Reputation: 27506

First of all - start using Generics. So your code woudl be

List<A> l = new ArrayList<A>();

And for your question, let your A class implement Comparable and override the method compareTo where you can put the expression for sorting. Example here

Upvotes: 0

jlordo
jlordo

Reputation: 37813

First of all, you don't have a List<Enum, Collection> as this is impossibile, you have a List<A> and shoud declare it as follows:

List<A> list = new LinkedList<>();

You are trying to instantiate in interface, which is not possible and is a compile time error.

If you want to sort a List of A's you should make a comparable:

public class A implements Comparable<A>

and override the compareTo() method as follows:

@Override
public int compareTo(A other) {
    return c.ordinal() - other.c.ordinal();
}

To sort your List you can call:

Collections.sort(list);

Upvotes: 0

bellum
bellum

Reputation: 3710

Here is what you have to do:

    List<A> l = new ArrayList<A>();
    l.add(new A("ZY", ComponentType.ACTION));  
    l.add(new A("ZY0", ComponentType.INSTRUCTION));  
    l.add(new A("ZY1", ComponentType.DOMAIN));  
    l.add(new A("ZY2", ComponentType.SERVICE));  
    l.add(new A("ZY3", ComponentType.INSTRUCTION));  
    l.add(new A("ZY4", ComponentType.ACTION));

    Collections.sort(l, new Comparator<A>()
    {
        @Override
        public int compare(A o1, A o2)
        {
            return o1.c.toString().compareTo(o2.c.toString());
        }
    });

Upvotes: 0

Subin Sebastian
Subin Sebastian

Reputation: 10997

Enum compareTo seems to be final and cant be overriden Why is compareTo on an Enum final in Java?

Just do Collections.sort() which will order the list in enum order as you need

Upvotes: 0

xiaofeng.li
xiaofeng.li

Reputation: 8587

According to java.util.Collections.sort, one way to do this is:

  1. Make class A implement the Comparable interface, this includes writing a int compare(A other) method.
  2. Call Collections.sort(l);

Upvotes: 1

Aleksander Blomsk&#248;ld
Aleksander Blomsk&#248;ld

Reputation: 18552

Make A implement Comparable. If you want to sort by the names of the enums, use this compareTo method:

public int compareTo(A a) {
    return a.c.getName().compareTo(c.getName());
}

If you want to sort by the order you have typed your enums, compare the ordinal values:

public int compareTo(A a) {
    return a.c.ordinal().compareTo(c.ordinal());
}

Upvotes: 3

Related Questions