当前位置: 首页 > 知识库问答 >
问题:

自定义比较器没有按预期对树集进行排序

耿招
2023-03-14

我有一个用类填充的树集。我想让这些按其继承排序,否则,只按其名称的字母顺序(以创建一个恒定的顺序)。但是由于某种原因,如果添加的类的顺序不正确,就会导致类的顺序不正确。

这是我的比较器:

class OrderedComparator implements Comparator<Class<?>> {

    @Override
    int compare(Class<?> clazz1, Class<?> clazz2) {
        if (clazz1 == clazz2) {
            return 0
        } else if (clazz1.isAssignableFrom(clazz2)) {
            return -1
        } else if (clazz2.isAssignableFrom(clazz1)) {
            return 1
        } else {
            return clazz1.canonicalName.compareTo(clazz2.canonicalName)
        }
    }
}

下面是一个测试失败的例子:

def 'OrderedSet is ordered in inheritence order, classes added multiple times'() {
    setup:
    Set<Class<?>> orderedSet = new TreeSet<>(new OrderedComparator())
    when:
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithoutClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithoutClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithoutClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithoutClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithClassAnnotation.class)
    orderedSet.add(com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithClassAnnotation.class)
    then:
    assert orderedSet[0] == com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithClassAnnotation.class
    assert orderedSet[1] == com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithClassAnnotation.class
    assert orderedSet[2] == com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithoutClassAnnotation.class
    assert orderedSet[3] == com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithoutClassAnnotation.class
    assert orderedSet[4] == com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithClassAnnotation.class
    assert orderedSet[5] == com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithClassAnnotation.class
    assert orderedSet[6] == com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithoutClassAnnotation.class
    assert orderedSet[7] == com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithoutClassAnnotation.class
}

排序集的实际值:

0 = {Class@1272} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithClassAnnotation"
1 = {Class@1474} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithoutClassAnnotation"
2 = {Class@1475} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithoutClassAnnotation"
3 = {Class@1271} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithClassAnnotation"
4 = {Class@1480} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithoutClassAnnotation"
5 = {Class@1286} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithClassAnnotation"
6 = {Class@1287} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithClassAnnotation"
7 = {Class@1476} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithoutClassAnnotation"

我的期望更像是:

0 = {Class@1271} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithClassAnnotation"
1 = {Class@1272} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithClassAnnotation"
2 = {Class@1474} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.TestResourceWithoutClassAnnotation"
3 = {Class@1475} "class com.benjaminsproule.swagger.gradleplugin.test.jaxrs.ExtendedTestResourceWithoutClassAnnotation"
4 = {Class@1286} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithClassAnnotation"
5 = {Class@1287} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithClassAnnotation"
6 = {Class@1476} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.TestResourceWithoutClassAnnotation"
7 = {Class@1480} "class com.benjaminsproule.swagger.gradleplugin.test.springmvc.ExtendedTestResourceWithoutClassAnnotation"

我在调试时确实注意到,并非每个项目都相互比较。

共有2个答案

韩捷
2023-03-14

尝试改变条件:

if (clazz1 == clazz2) {
    return 0;
} else if (clazz1.isAssignableFrom(clazz2)) {
    return 1; // this changed
} else if (clazz2.isAssignableFrom(clazz1)) {
    return -1; // this changed
} else {
    return clazz1.getCanonicalName().compareTo(clazz2.getCanonicalName());
}

因为我在测试*和扩展测试*类中看到了您的期望和实际排序之间的反转。

宫子晋
2023-03-14

考虑这些类

class A extends C {}

class B {}

class C {}

这里< code>A在< code>B之前(两者都不是另一个的子类,所以按字母顺序排列)。

类似地,B位于C

如果你的比较器是传递的,这意味着AC之前。然而

compare(A.class, C.class) == 1   // Because A is a subclass of C

意思是 A “大于”C

一旦您开始尝试使用无效的比较器进行排序,就不会指定行为。

 类似资料:
  • 我必须写一个程序 > 使用一个类ShopItem,其中一个项目的属性是:barCodeNumber、itemName、price和QuantityInStock。创建5个ShopItems实例(item1、item2、item3、item4和item5)的属性值为我自己的值。 为ShopItem使用一个比较器(BarcodeParator),它允许基于它们的barCodeNumber对ShopIt

  • 我有以下清单: 这是我的比较器函数: 我正在尝试使用它排序如下: 我不明白为什么第一个NaN不在列表的末尾。 我对升序排序列表的预期输出是: 我对降序排序列表的预期输出是: 在升序排序和降序排序的情况下,我希望NaNs在最后。 我知道sortwith使我们能够编写自己的比较器。有人能帮我吗?

  • 问题内容: 我需要使用自定义比较器对整数数组进行排序,但是Java的库没有为带有比较器的整数提供排序功能(比较器只能与对象一起使用)。有没有简单的方法可以做到这一点? 问题答案: 如果你无法更改输入数组的类型,则将执行以下操作: 这可以使用ArrayUtilscommons-lang项目轻松地在和之间进行转换,创建数组的副本,进行排序,然后将排序后的数据复制到原始数据上。

  • 要做到这一点,最干净的捷径是什么? 我知道它可以通过自定义比较器来实现。对于这种情况,难道没有现成的东西吗? 有点像这样:

  • 问题内容: 我知道有几个这样的问题,但是它们似乎对我没有用。 我有一个列表,5元素乘以50。我想通过对每个元素应用自定义比较功能来对列表进行排序。此函数计算要对元素进行排序的列表的适用性。我创建了两个函数,比较和适应性: 和 然后我尝试通过以下方式致电给他们: 要么 要么 要么 我也尝试了具有相同参数的list.sort()。但是无论如何,函数都不会将列表作为参数,而是作为参数。我不知道为什么,这

  • 引用:PriorityQueue的Java文档 ps:@user207421 Heapify算法可以在时间内将任何未排序的数组转换为堆,而不是。有很多关于Heapify的文章。堆也不是排序数组。它是一个具有堆属性的完整树,可以用数组进行编码。