基于枚举的java排序具有随机行为

fzwojiic  于 2021-07-09  发布在  Java
关注(0)|答案(3)|浏览(394)

对于下面的代码,我尝试根据枚举类型对bean进行排序。此bean的枚举类型也可以为null。
排序后的顺序应为:

A -> B -> C -> null.

运行以下代码后,元素的排序如下:

[A, A, C, B, B, null, C, null]

请帮忙

public class Bean implements Comparable<Bean> {

    enum Type {
      A, B, C
    }

    private Type type;
    private int i;
    private int j;

    public Bean(Type type, int i, int j) {
      this.type = type;
      this.i = i;
      this.j = j;
    }

    @Override
    public int compareTo(Bean that) {
       if (this.type == that.type) {
         return 0;
       }
       if (this.type != null && that.type != null) {
         if (this.type == type.A &&
            that.type == type.B) {
          return -1;
        }
        if (this.type == type.B &&
            that.type == type.C) {
          return -1;
        }
        if (this.type == type.A &&
            that.type == type.C) {
          return -1;
        }
        return 1;
      }

      return this.type == null ? 1 : -1;
    }

    @Override
    public String toString() {
      return "Bean{" + "type=" + (type != null ? type : "Unknown") + "}";
    }

    public static void main(String[] args) {
      Bean b1 = new Bean(Type.B, 1, 1);
      Bean b3 = new Bean(null, 3, 3);
      Bean b2 = new Bean(Type.C, 2, 2);
      Bean b0 = new Bean(Type.A, 0, 0);
      Bean b4 = new Bean(Type.B, 4, 4);
      Bean b5 = new Bean(null, 5, 5);
      Bean b6 = new Bean(Type.C, 6, 6);
      Bean b7 = new Bean(Type.A, 7, 7);

      List<Bean> list = new ArrayList<>();
      list.add(b1);
      list.add(b3);
      list.add(b2);
      list.add(b0);
      list.add(b4);
      list.add(b5);
      list.add(b6);
      list.add(b7);

      System.out.println(list);

      System.out.println(new PriorityQueue<Bean>(list));
    }
}
k2fxgqgv

k2fxgqgv1#

我看不出compareto有什么特别的问题,除了它的复杂性随着枚举数的增长而扩展。
问题是不同的:priorityqueue.tostring不会从队列中提取项,它只是打印底层的二进制堆结构。
请注意,二进制堆只是部分有序的。它确保了a[i]>a[2*i]和a[2*i+1],对于a[2*i]和a[2*i+1]的订购,不能事先说什么。
这个问题已经出现在stackoverflow中:priorityqueue.tostring元素顺序错误

ogsagwnx

ogsagwnx2#

你应该做的是:

enum Type {
    A, B, C, INVALID
}

然后

public Bean(Type type, int i, int j) {
    this.type = type == null ? Type.INVALID : type;
    this.i = i;
    this.j = j;
}

比较器应简单易读:

@Override
public int compareTo(Bean that) {
    return this.type.compareTo(that.type);
}

注意这是可能的,因为 Enum<E> 工具 Comparable<E> 通过枚举的自然顺序
这么做

System.out.println(list);
Collections.sort(list);
System.out.println(list);

将产生:

[Bean{type=B}, Bean{type=INVALID}, Bean{type=C}, Bean{type=A}, Bean{type=B}, Bean{type=INVALID}, Bean{type=C}, Bean{type=A}]
[Bean{type=A}, Bean{type=A}, Bean{type=B}, Bean{type=B}, Bean{type=C}, Bean{type=C}, Bean{type=INVALID}, Bean{type=INVALID}]
kknvjkwl

kknvjkwl3#

你没有考虑到所有可能的 this.type 以及 that.type . 你忘了: if (this.type == Type.B && that.type == Type.A) if (this.type == Type.C && that.type == Type.A) if (this.type == Type.C && that.type == Type.B) 然而,有一个更简单的方法。所有枚举常量都是可比较的。它们的自然顺序是它们在源代码中声明的顺序。所以你可以做:

if (this.type != null && that.type != null) {
    return this.type.compareTo(that.type);
}

相关问题