user1159819
user1159819

Reputation: 1679

Comparison method violates its general contract

I am getting the Comparison method violates its general contract exception with this compareTo method, but I can't track down what is exactly causing the issue. I am trying to sort files by their extension in a particular way. Mind you this doesn't happen for all phones, just ones that I don't have access to which makes it harder to test out.

public int compareTo(NzbFile another) 
{
    if (this.getFileName() != null && another.getFileName() != null)
    {
        if (this.getFileName().toLowerCase().endsWith(".nfo"))
            return -1000;
        else if (another.getFileName().toLowerCase().endsWith(".nfo"))
            return 1000;
        else if (this.getFileName().toLowerCase().endsWith(".sfv"))
            return -999;
        else if (another.getFileName().toLowerCase().endsWith(".sfv"))
            return 1001;
        else if (this.getFileName().toLowerCase().endsWith(".srr"))
            return -998;
        else if (another.getFileName().toLowerCase().endsWith(".srr"))
            return 1002;
        else if (this.getFileName().toLowerCase().endsWith(".nzb"))
            return -997;
        else if (another.getFileName().toLowerCase().endsWith(".nzb"))
            return 1003;
        else if (this.getFileName().toLowerCase().endsWith(".srt"))
            return -996;
        else if (another.getFileName().toLowerCase().endsWith(".srt"))
            return 1004;
        else
            return this.getFileName().compareTo(another.getFileName());
    }
    else if (this.getFileName() != null && another.getFileName() == null)
    {
        return -995;
    }
    else if (this.getFileName() == null && another.getFileName() != null)
    {
        return 1005;
    }
    else
    {
        return this.getSubject().compareTo(another.getSubject());
    }

}

Upvotes: 1

Views: 2450

Answers (2)

Louis Wasserman
Louis Wasserman

Reputation: 198211

If your file names are the same, and both e.g. end in .nfo, then this will return that they aren't equal. I assume that they're meant to be equal.

I strongly suspect that there's a Better Way to Do This. I'll use Guava for my example, but it's not strictly necessary.

static final List<String> EXTENSIONS = ImmutableList.of("nfo", "sfv", "srr", "nzb", "srt");
final Ordering<String> fileNameOrdering = new Ordering<String>() {
  public int compare(String a, String b) {
    String extA = Files.getFileExtension(a);
    String extB = Files.getFileExtension(b);
    int extAIndex = EXTENSIONS.indexOf(extA);
    int extBIndex = EXTENSIONS.indexOf(extB);
    if ((extAIndex >= 0) == (extBIndex >= 0)) { // if they are both known extensions or both unknown
      return extAIndex - extBIndex;
    } else if (extAIndex < 0) { // a is unknown, b is known
      return -1;
    } else if (extBIndex < 0) { // b is unknown, a is known
      return 1;
    }
    return a.compareTo(b);
  }
}.nullsLast();
return new Ordering<NzbFile>() {
  public int compare(NzbFile a, NzbFile b) {
    return ComparisonChain.start()
      .compare(a.getFileName(), b.getFileName(), fileNameOrdering)
      .compare(a.getSubject(), b.getSubject())
      .result();
  }
};

Upvotes: 5

Chris Nash
Chris Nash

Reputation: 3061

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.

This doesn't seem to happen if you compare two files with the same extension. Comparing say a.nfo and b.nfo returns -1000, both ways round.

Upvotes: 2

Related Questions