0

我的想法是按层对一些实体(只是一些整数)进行排序。我发现有人似乎有同样的问题(我认为),但我不明白解决方案。每个实体的层存储在一个数组中。我对图层使用了枚举。

public enum Layer {
DEFAULT,
BACKGROUND,
FOREGROUND,
HUD_0,
HUD_1
}

所以我不知道我是否误解了比较器的工作方式,或者我是否只是因为实体是整数而遇到问题......

final Layer[] layers = {Layer.BACKGROUND, Layer.HUD_1, Layer.DEFAULT, Layer.DEFAULT, Layer.HUD_0, Layer.HUD_1};
    TreeSet<Integer> sorted = new TreeSet<Integer>(new Comparator<Integer>() {
        @Override
        public int compare(Integer entity1, Integer entity2) {
            //Integer layer1 = layers[entity1].ordinal();
            //Integer layer2 = layers[entity2].ordinal();
            //return layer1 < layer2 ? -1 : (layer1 > layer2 ? 1 : 0);
            return layers[entity1].compareTo(layers[entity2]);
        }
    });
    sorted.add(0);//bg
    System.out.println(sorted.toString());
    sorted.add(4);//hud0
    System.out.println(sorted.toString());
    sorted.add(2);//def
    System.out.println(sorted.toString());
    sorted.add(3);//def
    System.out.println(sorted.toString());
    sorted.add(1);//hud1
    System.out.println(sorted.toString());
    sorted.add(5);//hud1
    System.out.println(sorted.toString());

这是输出:

[0]
[0, 4]
[2, 0, 4]
[2, 0, 4]
[2, 0, 4, 1]
[2, 0, 4, 1]

最后一个实际上应该是 [2, 3, 0, 4, 1, 5]

我读到 TreeSet 只存储每个元素一次,因为它是一个 Set 但我不知道为什么它使用该层而不是我实际想要插入的实体。

4

3 回答 3

3

从 TreeSet 的角度来看,两个元素相等 if item1.compareTo(item2) == 0。在您的情况下,Layer.HUB_1在您的数组中出现两次,并且两个项目将被视为相等,因此只会添加一个。

于 2013-07-02T15:55:23.743 回答
2

之所以会这样,是因为 TreeSet 是这样定义的:“TreeSet 实例使用它的 compareTo(或 compare)方法执行所有元素比较,因此从集合的角度来看,被此方法视为相等的两个元素是相等的。 " java.util.TreeSet

您可以引入一个决胜局,它将在同一层中的不同对象之间强加一个顺序 - 如果您没有可以使用的更有意义的东西,它可能只是一个任意序列号。不同层中的对象仍将按层排序。

于 2013-07-02T15:55:42.160 回答
0

问题最终是 TreeSet 将(作为一个集合)只保存一次元素,并且它需要一种方法来知道它是否已经包含一个元素,并且它使用您提供的 Comparator 来做到这一点。由于您的比较器使用枚举进行排序,因此如果枚举匹配,Treeset 将两个条目视为相等。

有关详细信息,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html,特别是段落

请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以获得与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但是 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

最终,如果您想使用 TreeSet 对枚举进行排序,则需要扩展比较逻辑以在枚举匹配时回退到其他内容。就像是

public int compare(Integer entity1, Integer entity2) {
    int returnValue = layers[entity1].compareTo(layers[entity2]);
    if(returnValue == 0){
        returnValue = entity1.compareTo(entity2);
    }
}

这使得实体不匹配(并且无法添加到 TreeSet)只是因为枚举匹配。

于 2013-07-02T15:57:34.900 回答