user1120007
user1120007

Reputation: 268

Collections.sort throws IllegalArgumentException

i am trying to sort a list of object that holds string and a double value:

lock.tryLock();
    if (testTagRev.size() > 0)
Collections.sort(testTagRev, documentSampleComperator);
lock.unlock();

documentSampleComperator is a type documentSampleComparer:

class documentSampleComparer implements Comparator<DocumentSample> {
    @Override
    public int compare(DocumentSample x, DocumentSample y) {
        int ans = x.getText().toString().compareTo(y.getText().toString());
        // ans = utils.listToString(x.getText(), ' ').compareTo(utils.listToString(y.getText(),' ')); also didn't work
        if (ans == 0)
            return Integer.compare(x.hashCode(), y.hashCode());
        else return ans;
    }
}

even though the compactor is transitive i still get this exception :

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method     violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:747)
    at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at Trainer.MCobjectStream.<init>(MCobjectStream.java:64)
at Trainer.filterRev.<init>(filterRev.java:64)
at Trainer.Train.main(Train.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

I am using jdk 1.7.0_45 , can you see where is the problem ?

Edit: utils.listToString turn's list of string to a string, added the lock code and comment the line that i was trying to make it work before . also i should mention that the exception only occurred sometimes but i am not using threads .

Upvotes: 1

Views: 1537

Answers (2)

bcorso
bcorso

Reputation: 47176

Implementing Comparator should not involve the hashCode of the Objects. Usually you just compare each attribute in order of their importance. In your example, if the text is the only thing you want to compare against then it should just be:

Collections.sort(catalog, new Comparator<DocumentSample>() {
    @Override
    public int compare(DocumentSample x, DocumentSample y) {
        return x.getText().toString().compareTo(y.getText().toString());
    }
});

By comparing the default implementation of hashCode (which returns an integer representation of the objects internal address) you are saying that two objects will be considered equal if and only if they are the same object in memory.

Upvotes: 1

Try to use inner class(without that wierd 2.line in method compare).

 Collections.sort(catalog, new Comparator<DocumentSample>() {
        @Override
        public int compare(DocumentSample x, DocumentSample y) {
            int ans = x.getText().toString().compareTo(y.getText().toString());
            if (ans == 0) {
                return Integer.compare(x.hashCode(), y.hashCode());
            } else {
                return ans;
            }
        }
    }
);

Upvotes: 0

Related Questions