|
An implementation of the class comparator that seems to work is:
class ClassHierarchyComparator implements Comparator<Class<?>> { @Override public int compare(Class<?> c1, Class<?> c2) { if (c1.equals(c2)) { return 0; }
else if (Object.class.equals(c1) || Object.class.equals(c2)) { return c1.isAssignableFrom(c2) ? 1 : -1; }
else if (c1.isAssignableFrom(c2)) { return 1; }
else if (c2.isAssignableFrom(c1)) { return -1; }
else { return compare(c1.getSuperclass(), c2.getSuperclass()); }
} }
But works only for classes. However from what you have described the specific comparator is used to sort Interfaces, (should be called InterfaceHierarchyComparator). IMHO this task is more complex due to the following facts:
-
interfaces can extend multiple interfaces
-
an interface can extend the same subset of interfaces with some of its superinterface(s).
This means that the interfaces hierarchy is not a tree, but a graph (with no circular references).
I've created an implementation that seems to work fine for interfaces, but I'm not sure whether it is efficient.
class InterfaceHierarchyComparator implements Comparator<Class<?>> { /Interface whose class is used in recursion to mark the parent of an interface that does not extend any other interface/ private static interface RootInterface{}
@Override public int compare(Class<?> c1, Class<?> c2) { int retVal; if (c1.equals(c2)) { retVal = 0; }
else if (c1.equals(RootInterface.class)) { retVal = 1; } else if (c2.equals(RootInterface.class)) { retVal = -1; } else if (c1.isAssignableFrom(c2)) { retVal = 1; }
else if (c2.isAssignableFrom(c1)) { retVal = -1; }
else { /*in this case we will compare the most deep the most deep from the parents of from each of the two interfaces.*/ List<Class<?>> c1Interfaces = Arrays.asList(c1.getInterfaces()); List<Class<?>> c2Interfaces = Arrays.asList(c2.getInterfaces()); Collections.sort(c1Interfaces, new InterfaceHierarchyComparator()); Collections.sort(c2Interfaces, new InterfaceHierarchyComparator()); Class<?> c1ParentInterfaceToCompare = c1Interfaces.isEmpty() ? RootInterface.class : c1Interfaces.get(0); Class<?> c2ParentInterfaceToCompare = c2Interfaces.isEmpty() ? RootInterface.class : c2Interfaces.get(0); retVal = compare(c1ParentInterfaceToCompare, c2ParentInterfaceToCompare); }
return retVal; } }
//Examples used: interface IfaceL {} interface IfaceK extends IfaceL{} interface IfaceA1 {} interface IfaceA2 {} interface IfaceB extends IfaceA1, IfaceA2 {} interface IfaceC extends IfaceB, IfaceA1 {} interface IfaceD extends IfaceK, IfaceA1, IfaceC {} interface IfaceE extends IfaceC, IfaceA1, IfaceA2 ,IfaceD , IfaceK{}
List list = new ArrayList(); list.add(IfaceA1.class); list.add(IfaceL.class); list.add(IfaceK.class); list.add(IfaceC.class); list.add(IfaceE.class); list.add(IfaceB.class); list.add(IfaceA2.class); list.add(IfaceD.class); Collections.shuffle(list, new Random(System.currentTimeMillis())); Collections.sort(list, new InterfaceHierarchyComparator()); System.out.println(list);
Result: IfaceE,IfaceD,IfaceC,IfaceB,IfaceK,IfaceA1,IfaceA2,IfaceL
|