0

Scenario

I got an Object which has a startDate and an endDate. If both are not null the timeDiff will be set, calculating the time difference between these two dates in Long.

Use Case

All Objects with a timeDiff should be first, rest last.

Comparator

HFehlerProtPairComparator

if (sortFieldName.equals(HFehlerProtPairFields.EREIGNISDATUM_DIFFERENZ.getName())) {
            if (null != firstO.getStartDate() && null != firstO.getEndDate()
                    && null != secondO.getStartDate() && null != secondO.getEndDate()) {
                compare = firstO.getTimeDiff().compareTo(secondO.getTimeDiff());
            } else {
                compare = -1;
            }

        }

I have no idea what I'm missing and debugging won't help me here. I tried verifying it on paper and I don't see my error there too.

Call Hierarchy

comp = new HFehlerProtPairComparator(field.getName(), SortType.ASC.name());
Error ==> Collections.sort(unsortedHFehlerProtPairList, comp);

Stack

at java.util.TimSort.mergeHi(TimSort.java:899)
at java.util.TimSort.mergeAt(TimSort.java:516)
at java.util.TimSort.mergeForceCollapse(TimSort.java:457)
at java.util.TimSort.sort(TimSort.java:254)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at uebergreifendeereignis.UeHFehlerProtPairListController.sortBySortMap(UeHFehlerProtPairListController.java:360)
Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
0x45
  • 779
  • 3
  • 7
  • 26

2 Answers2

2

If you have an object with neither startDate nor endDate set and you compare it to itself, your comparator gives -1 as the result. The result should be 0, since an object should not be less then itself..

juwil
  • 422
  • 3
  • 9
2

The problem is that in some circumstances, your code returns -1 when comparing A to B, and also when comparing B to A. For example, imagine you have object A, which has no start date, and object B, which has no end date. Now, when your comparator is called with the parameter list (A, B), it returns -1, indicating that A is less than B.

But later on, it's possible that the comparator will be called with the parameter list (B, A). It, too returns -1, meaning that B < A.

That violates the contract for the comparator. The rules say that if the comparator returns -1 for (A, B), then it must return 1 for (B, A). That is, if A < B, then B > A. Your code doesn't meet that contract.

For your code to work, you have to decide what it means to compare time differences when the start or ending time is not defined. If A.startDate is null, then timeDiff is undefined. If B has a valid time diff, should B be considered greater than, equal to, or less than A?

As with my previous answer, you have several conditions to consider.

A.timeDiff  B.timeDiff    result
 undefined   undefined    equal
 undefined   valid        ??
 valid       undefined    ??
 valid       valid        A.timeDiff.compareTo(B.timeDiff)

It's up to you to decide what the result should be when one or the other is undefined. But whatever you do, the resulting code must honor the contract.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351