Java 与经济数据的比较逻辑错误-比较方法违反其总合同

Java 与经济数据的比较逻辑错误-比较方法违反其总合同,java,compare,illegalargumentexception,compareto,Java,Compare,Illegalargumentexception,Compareto,我知道我的比较方法有些问题,但不确定在哪里 以下是我试图排序的数据: 我正在查看许多.txt文件(每行大约20000行),其中每行都有一个数据点。我提取一个会计年度(格式为yyyqx,其中X表示会计季度为1-4)并将其存储为字符串。我还提取了一个行业代码(六位整数)和一个价格指数(存储为双精度)。这存储在数据点对象中 我希望输出为三列,一列为会计年度,一列为行业代码,一列为价格指数。我希望对数据进行格式化,以使会计年度有序(1991q1、1991q2、…、1992q1等),行业代码至少按最大值排

我知道我的比较方法有些问题,但不确定在哪里

以下是我试图排序的数据:

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

我希望输出为三列,一列为会计年度,一列为行业代码,一列为价格指数。我希望对数据进行格式化,以使会计年度有序(1991q1、1991q2、…、1992q1等),行业代码至少按最大值排序。因此,会计年度列将有许多针对每个行业代码的1991q1条目,其中包含该季度的价格指数。然后,当1991q1的所有行业代码都已用尽时,将列出1991q2的所有行业代码,以此类推

为了实现这一点,我构建了DataPoint compareTo方法,如下所示:

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;
        }
    }
}
fiscalQuarter是包含YYYYqX会计年度的字符串变量的名称

当我前面提到行业代码时,实际上会有一个行业代码(四位整数)或一个行业代码(六位整数)。数据点不会同时具有这两个值(它没有的一个值被初始化为0),因此这是在compareTo方法中检查sectorCode或industryCode的值

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

下面是我试图调用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;
}
公共静态列表格式行业数据(列表数据列表){
列表数据=新的ArrayList();
用于(数据列表:数据列表){
data.addAll(list.getIndustryPoints());
}
收集、分类(数据);
返回数据;
}
有人能看出我的逻辑在compareTo方法中哪里出错了吗

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


此外,与具有行业值的数据点相比,没有具有行业值的数据点-它们存储在单独的列表中,并且只在彼此之间进行比较和排序。

您的逻辑似乎不完整

如果
this
instance>0的sectorCode,则按sectorCode进行比较,但不处理p.sectorCode为0的情况,而按industryCode进行比较,但不处理p.industryCode B和B>A不能同时为真的情况

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

    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
    }

此外,如果
industryCode==p.getIndustryCode()
(两者均为正值)或
sectorCode==p.getSectorCode()
(两者均为正值),则可能应返回0。

在同一会计年度,行业/行业代码不会重复。我没提那件事,我道歉。因此,如果会计年度相等,那么我比较部门/行业代码,它们将永远不会相同。@eugene1832但如果在同一会计年度,一个对象只有部门代码,而另一个对象只有行业代码,该怎么办?那不可能吗?啊,我明白你的意思了。因此,数据点具有扇区代码或行业代码,并存储在两个单独的列表中,一个是具有扇区值的数据点,另一个是具有行业值的数据点。这些列表从不合并在一起,因此它们只是在部门值或行业值之间排序,而不是在两者之间排序。例如,我在底部包含的formatIndustryData方法对所有文件中包含行业值的所有数据点进行排序。还有另一种方法可以对所有具有扇区值的数据点执行此操作。@eugene1832无论您认为它是否适用于您试图排序的特定列表,契约都是非常具体的-
实现者必须确保sgn(x.compareTo(y))==-sgn(y.compareTo(x))对于所有的x和y.
因为你违反了合同,你不能期望它起作用。我对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
    }