Search code examples
javaandroidcollectionscomparator

Fatal Exception: java.lang.IllegalArgumentException: Comparison method violates its general contract


I know there many similar questions and I have received big help by reading answers to those questions, however I am not able to see how is my client facing this problem. And there is only one client who is facing this problem.

I have a List, and I am sorting that list using Comparator interface. Does any of you see problem with the following code?

    private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
        @Override
        public int compare(BiologySample left, BiologySample right) {
            if (left == right || (left != null && right != null && left.getSampleDateTime() == right.getSampleDateTime())) {
                return 0;
            }

            if (left == null || left.getSampleDateTime() == null) {
                return 1;
            }

            if (right == null || right.getSampleDateTime() == null) {
                return -1;
            }

            return right.getSampleDateTime().compareTo(left.getSampleDateTime());
        }
    }

And this how I am calling this function

Collections.sort(biologySamples, new BiologySamplesComparator());

I know that the main problem in this kind of scenario is Transitivity. However I couldn't figure what is violating that rule.

This how getSampleDateTime() is returning date Fri Apr 09 17:00:00 PDT 2021


Update This is how I was able to fix my problem. I hope this helps, I was stuck for so long on this problem.

    private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
        @Override
        public int compare(BiologySample left, BiologySample right) {
            if (left == null) {
                if (right == null) {
                    return 0;
                } else {
                    return 1;
                }
            } else if (right == null) {
                return -1;
            } else if (left == right) {
                return 0;
            }
            if (left.getSampleDateTime() == null) {
                if (right.getSampleDateTime() == null) {
                    return 0;
                } else {
                    return 1;
                }
            } else if (right.getSampleDateTime() == null) {
                return -1;
            } else if (left.getSampleDateTime() == right.getSampleDateTime()) {
                return 0;
            }

            return right.getSampleDateTime().compareTo(left.getSampleDateTime());
        }
    }

Solution

  • I was missing some conditional for some cases and this is how I was able to solve my problem.

        private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
            @Override
            public int compare(BiologySample left, BiologySample right) {
                if (left == null) {
                    if (right == null) {
                        return 0;
                    } else {
                        return 1;
                    }
                } else if (right == null) {
                    return -1;
                } else if (left == right) {
                    return 0;
                }
                if (left.getSampleDateTime() == null) {
                    if (right.getSampleDateTime() == null) {
                        return 0;
                    } else {
                        return 1;
                    }
                } else if (right.getSampleDateTime() == null) {
                    return -1;
                } else if (left.getSampleDateTime() == right.getSampleDateTime()) {
                    return 0;
                }
    
                return right.getSampleDateTime().compareTo(left.getSampleDateTime());
            }
        }
    

    courtesy of Why does my compare methd throw IllegalArgumentException sometimes?