1

I'm trying to sort a list of Product objects by their useby Dates, but some of the objects may have their Date useby = null

What I want to do is sort the list by "useby" Dates, and put all the Objects that has Date useby = null on the bottom or on the top of the list.

public static void sort() {
        Collections.sort(list, new Comparator<Product>() {
            public int compare(Product o1, Product o2) {
                if (o1.getUseDate() == null || o2.getUseDate() == null) {
                    return 0;
                } else {
                    return o1.getUseDate().compareTo(o2.getUseDate());
                }
            }
        });
    }

This is my code and I don't know how to fix this.

3 Answers 3

4

if (o1.getUseDate() == null || o2.getUseDate() == null). Here you are checking if either of the two Product's has a null date. If even one of them does the return result of 0 means that the Comparator will see them as equal. Even if just one of them has a null date. Here you probably want to do some more in-depth checking. The following code will result in Product's with null Dates being put at the start.

if(o1.getUseDate() == null && o2.getUseDate() == null)
    return 0; //They are both null, both equal
if(o1.getUseDate() == null && o2.getUseDate() != null)
    return -1; // The first is null and the second is not, return the first as lower than the second
if(o1.getUseDate() != null && o2.getUseDate() == null)
    return 1; //The first is not null and the second is, return the first as higher than the second
else
    return o1.getUseDate().compare(o2.getUseDate()); //Return the actual comparison

This is obviously a little verbose, but it should give you an idea as to what you should actually be looking for.

Sign up to request clarification or add additional context in comments.

Comments

1

return 0; means that compared elements are equal (in other words you shouldn't swap them).

In case of nulls consider

  • returning 0 if both values are null (first value is same as second value - don't swap)
  • returning -1 if first value is null but second is not null (first element is lesser than second - don't swap)
  • returning 1 if second value is null and first is not null (first element is greater than second - swap them)

Comments

1

From compare javadoc:

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

But from this line of your code:

if (o1.getUseDate() == null || o2.getUseDate() == null) {
   return 0;

we can see that you're practically telling the comparator to consider useDates as being equal when at least one of them is null, and this is not what you want.

Since null means "nothing", it's quite weird to compare the concept of nothing with a date, but if you want to allow null values, then you have to handle this situation properly, resulting into a more vorbose code:

if(o1.getUseDate() == null){
    return o2.getUseDate() == null ? 0 : -1; //or +1 if you want null values at the bottom of your list
}
if(o2.getUseDate() == null){
    return o1.getUseDate() == null ? 0 : -1; // or +1 ...
}
return o1.getUseDate().compare(o2.getUseDate()); // 2 non null dates, do a real comparison

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.