如何按枚举顺序对List<Enum, Collection>进行排序?

8

枚举:

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

A类:

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

 }   

代码:

 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));  

如何按照枚举顺序对列表进行排序?

1
我不明白你想要什么...你的例子无法编译,因为java.util.List.add不接受两个对象参数。 - Aleksander Blomskøld
抱歉...我错过了类定义...刚刚编辑完毕。现在,问题已经完整了。 - Shashi
1
你是希望按照"ZY"、"ZY0"的顺序排序,还是按照ACTION、INSTRUCTION等排序? - Random42
按照 ACTION、INSTRUCTION 的顺序排序。顺序定义在 ComponentType 中,例如 INSTRUCTION、ACTION、SERVICE、DOMAIN。 - Shashi
Collections.sort(list) 的结果是什么?我相信它会按枚举顺序排序。 - Subin Sebastian
1
@SubinS:只有当列表中的元素是“可比较的”时,Collections.sort(list) 才能正常工作。否则,您需要自己提供一个 Comparator - Costi Ciudatu
10个回答

7

您应该简单地委托给已经提供的枚举compareTo方法,它反映了声明顺序(基于ordinal值):

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

或者,如果你认为组件类型为你的元素提供了“自然顺序”,你可以使A类本身实现Comparable并将compareTo方法委托给ComponentType


1
他想按照枚举顺序进行操作,不需要对枚举名称进行字母顺序排序,只需按照枚举顺序排序即可。因此,使用 Collections.sort(list) 应该可以实现。 - Subin Sebastian
你为什么提到“枚举名称的字母顺序”?你可能评论错了答案(我看到还有另一个答案涉及到你提到的顺序)? :) - Costi Ciudatu
是的,我认为那是一个错误,我可能是指其他的评论。但是 Collections.sort() 不会起作用吗? - Subin Sebastian
你的答案是对的。我评论了bellium的答案,因为输出与问题所要求的不同... 如果排序顺序是枚举中定义的顺序,则将使用bellium的答案。 - Shashi

3

我遇到了同样的问题,但是我无法修改我的Enum类并且顺序是错误的。这就是为什么我不能在枚举对象上使用简单的compareTo。解决方案非常简单,只需为每个Enum字段分配int值,然后进行比较:

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;

        }
    }

}

并且:
Collections.sort(list, new MyComparator);

3

实现Comparable接口。如果你想按枚举的名称进行排序,请使用以下compareTo方法:

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

如果您想按照枚举类型的输入顺序排序,可以比较它们的顺序值(ordinal values)。
public int compareTo(A a) {
    return a.c.ordinal().compareTo(c.ordinal());
}

1

看起来你应该使用EnumMap,因为它们按键自然排序。

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));

这种方法唯一的问题是,“ZY”和“ZY0”会丢失,因为代码部分添加了同类型的其他实例。 - Costi Ciudatu
True,EnumMap不允许重复。已修复答案。 - Peter Lawrey
2
然而,考虑到问题标题中提到的奇怪类型,你可能离答案最近。如果他实际上是指 Map<Enum, Collection>,那么你所需要做的就是将你的 EnumMap 更改为 EnumMap<ComponentType, Collection<A>> - Costi Ciudatu

1
如果需要根据ENUM对类进行排序,为了保持一致性,我们必须使用ENUM的compareTo(如果是final)方法。
将此方法添加到A类中将有助于保持一致的行为。
@Override
public int compareTo(A o) {
    return this.c.compareTo(o.c);
}

1
根据 java.util.Collections.sort,一种方法是:
  1. class A 实现 Comparable 接口,这包括编写一个 int compare(A other) 方法。
  2. 调用 Collections.sort(l);

0

你需要做的是:

    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());
        }
    });

0

首先,你没有一个 List<Enum, Collection>,因为这是不可能的,你有一个 List<A>,应该按照以下方式声明:

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

你正在尝试实例化一个接口,这是不可能的,并且会导致编译时错误。

如果你想对 A 的 List 进行排序,你应该使其可比较:

public class A implements Comparable<A>

并重写 compareTo() 方法如下:

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

要对您的列表进行排序,您可以调用:

Collections.sort(list);



0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接