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

与经济数据的比较逻辑错误——比较法违反其一般契约

蒯坚白
2023-03-14

我知道我的comareTo方法有一些问题,但不确定在哪里…

这是我试图排序的数据:

我正在查看许多. txt文件(每个大约20,000行),其中每一行都有一个数据点。我正在提取财政年度(格式为YYYYqX,其中X为财政季度的1-4)并将其存储为字符串。我还提取了行业代码(六位整数)和价格指数(存储为双精度)。这存储在DataPoint对象中。

我希望输出是三个列,一个是财政年度,一个是行业代码,一个是价格指数。我希望数据格式化,使财政年度按顺序排列(1991q1、1991q2、…、1992q1等),行业代码排序最小到最大值。因此,财政年度列将为每个行业代码提供许多1991q1条目,其中包含该季度的价格指数。然后,当1991q1的所有行业代码都已用尽时,将列出1991q2的所有行业代码,等等。

为了实现这一点,我构建了如下的数据点比较方法:

public int compareTo(DataPoint p) {
    int fiscalResult = compareFiscal(p.getFiscalQuarter());
    if (fiscalResult > 0) {
        return fiscalResult;
    } else if (fiscalResult < 0) {
        return fiscalResult;
    } else {
        if (sectorCode > 0) {
            if (sectorCode > p.getSectorCode()) {
                return sectorCode - p.getSectorCode();
            }
            else if (sectorCode < p.getSectorCode()){
                return p.getSectorCode() - sectorCode;
            }
            else {
                return 0; // Should never happen
            }
        }
        else if (industryCode > 0) {
            if (industryCode > p.getIndustryCode()) {
                return industryCode - p.getIndustryCode();
            }
            else if (industryCode < p.getIndustryCode()) {
                return p.getIndustryCode() - industryCode;
            }
            else {
                return 0; // Should never happen
            }
        }
        // These should never be reached
        else if (p.getSectorCode() > 0) {
            return -1;
        }
        else if (p.getIndustryCode() > 0) {
            return -1;
        }
        else {
            return 0;
        }
    }
}

其中comareF的(字符串)方法只是:

public int compareFiscal(String otherFiscal) {
    return fiscalQuarter.compareTo(otherFiscal);
}

fiscalQuarter是包含YYYqX会计年度的字符串变量的名称。

我前面说的行业代码,其实要么会有一个部门代码(是四位整数),要么会有一个行业代码(六位整数)。一个数据点不会两者都有(它没有的那个被初始化为0),所以这就是在compareTo方法中检查sectorCode或industryCode的值。

我可以毫无问题地在一个文件中对这些点的列表进行排序,但是在程序结束时,我从每个文件中取出所有的数据点,并将它们放入一个新的数组列表(两个列表,一个用于扇区代码,一个用于行业代码。在任何时候,部门和行业代码都不会被排序在一起),并调用Collections.sort on this。这是抛出错误的一点。

这里有一点我试图调用Collections.sort方法(对于行业列表,一个相同的方法用于部门列表)。DataList只是代表一个文件的另一个对象,包含两个列表,一个是所有部门数据点,一个是所有行业数据点。数据列表列表只包含从每个文件创建的所有数据列表。我不认为这说明了什么,只是为了相关性:

public static List<DataPoint> formatIndustryData(List<DataList> dataLists) {
    List<DataPoint> data = new ArrayList<>();
    for (DataList list : dataLists) {
        data.addAll(list.getIndustryPoints());
    }
    Collections.sort(data);
    return data;
}

有人能看出我在compareTo方法中的逻辑哪里出错了吗?

编辑:我忘了提到,如果财政年度不同,我们永远不会得到一个等于另一个的部门/行业代码。(例如,在同一财政年度,同一行业代码永远不会有两个价格指数,因为这没有多大意义)。

此外,在任何时候都不能将具有行业值的数据点与具有行业值的数据点进行比较——它们存储在单独的列表中,只能相互比较和排序。

共有1个答案

解阳荣
2023-03-14

你的逻辑似乎不完整。

如果实例的sectorCode

同样,如果实例的行业代码

您应该决定两个属性中的哪一个——区间代码和行业代码——优先。

假设对象A的部门代码为5,行业代码为0。对象B的部门代码为0,行业代码为6。

A.compareTo(B)返回1
B.compareTo(A)也返回1

这破坏了compareTo的契约,因为

如果要先按扇区代码进行比较,则代码应如下所示:

    if (sectorCode > 0) {
        if (sectorCode > p.getSectorCode()) {
            return 1;
        }
        else {
            return -1;
        }
    } else if (p.getSectorCode() > 0) {
        return -1;
    } else if (industryCode > 0) {
        if (industryCode > p.getIndustryCode()) {
            return 1;
        }
        else {
            return -1;
        }
    } else if (p.getIndustryCode() > 0) {
        return -1;
    } else {
        return 0; // Should never happen
    }

此外,您可能应该返回0,如果行业代码==p.get行业代码()(当两者都是正数时)或sectorCode==p.getSectorCode()(当两者都是正数时)。

 类似资料:
  • 我知道有很多问题与这个主题有关,但我不能完全理解是什么导致了这个错误 有人知道为什么它不起作用以及如何修复它吗?

  • 问题内容: 我看到了很多与此有关的问题,并试图解决该问题,但是经过一个小时的搜索和大量的试验和错误后,我仍然无法修复它。我希望你们中的一些人能抓住问题。 这是我得到的: 这是我的比较器: 任何想法? 问题答案: 异常消息实际上是描述性的。这里所指的合同是传递:如果和那么对于任意的。我用纸和铅笔检查了一下,你的代码似乎有几个孔: 如果你不返回。 如果id不相等,则返回。你应该返回-1或1根据哪个ID

  • 我目前正在Java中对集合进行排序。我收到了错误消息“比较方法违反了它的一般契约”。我也理解这个错误消息,但我(主要)使用Long类型的构建比较方法。所以我不知道,在这种情况下,排序方法仍然违反了契约。这是我的代码: 这里是错误:

  • 我有一个类字段,和。我需要使用对它们进行排序,但我得到了一个异常: java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 我的< code>compareTo方法: 请帮我找出compareTo方法中的错误。谢了。

  • 问题内容: 我有以下代码: 每次我运行此代码时,都会出现此错误: 我使用OpenJDK7u3,当对象相等时返回0。有人可以向我解释这个错误吗? 问题答案: 如果您有任何NaN值,则可能会遇到这种情况: 例如: 所有 这些打印。因此,您可能会遇到以下两种情况:两个非NaN值都被认为与NaN“相等”,但是一个大于另一个。基本上,您应该弄清楚如何处理NaN值。当然,还要检查这确实是问题所在……您是否真的

  • 我已经尝试了许多可能的解决方案,在网上给出的像设置系统属性和转换在双,但仍然得到相同的错误: 以下是我的代码: