Why does my compare methd throw IllegalArgumentException sometimes?

穿精又带淫゛_ 提交于 2019-12-05 05:50:02

Let's look at your first compare method :

    public int compare(FileItem o1, FileItem o2) {

        int result = 0;
        if (o1 != null && o2 != null) {

            String n1 = o1.getFileName();
            String n2 = o2.getFileName();

            if (n1 != null && n2 != null)
                result = n1.compareTo(n2);
        }

        return result;
    }

Suppose you are comparing two FileItems (let's call them o1 and o2), one with a file name and the other without (i.e. null file name). Your method will return 0.

Now if you compare o2 with another FileItem (o3) for which the file name is not null, you return 0 again.

But if you compare o1 to o3, since both of them have non null file name, the comparison returns -1 or 1 (assuming the file names are different).

Therefore your comparison is inconsistent since it's not transitive.

If one element lacks a property required for the comparison and the other doesn't, you shouldn't return 0. You should decide whether to return 1 or -1 (depending whether, for example, the FileItems with null names should be ordered before or after the FileItems with non null names).

For example :

public int compare(FileItem o1, FileItem o2) 
{
    if (o1 == null) {
        if (o2 == null) {
            return 0;
        } else {
            return 1; // this will put null in the end
        }
    } else if (o2 == null) {
        return -1;
    }
    String n1 = o1.getFileName();
    String n2 = o2.getFileName();
    if (n1 == null) {
        if (n2 == null) {
            return 0;
        } else {
            return 1; // this will put null names after non null names 
        }
    } else if (n2 == null) {
        return -1;
    }
    return n1.compareTo(n2);
}
OldCurmudgeon

This is a common mistake with comparators - you are not handling null consistently. The usual pattern would look like this:

public int compare(FileItem o1, FileItem o2) {
    // null == null
    if (o1 == null && o2 == null) {
        return 0;
    }
    // null < not null
    if (o1 == null || o2 == null) {
        return -1;
    }
    // Neither can be null now so this is safe.
    String n1 = o1.getFileName();
    String n2 = o2.getFileName();
    // Same logic again.
    if (n1 == null && n2 == null) {
        return 0;
    }
    if (n1 == null || n2 == null) {
        return -1;
    }
    return n1.compareTo(n2);
}

Added

Note that this implementation also a common mistake as I am allowing compare(null,not_null) to equal compare(not_null,null) which also violates the contract - please use @Eran's solution or something like this.

public int compare(FileItem o1, FileItem o2) {
    // null == null
    if (o1 == null && o2 == null) {
        return 0;
    }
    // null != not null
    if (o1 == null || o2 == null) {
        // Swap these around if you want 'null' at the other end.
        return o1 == null ? -1: 1;
    }
    // Neither can be null now so this is safe.
    String n1 = o1.getFileName();
    String n2 = o2.getFileName();
    // Same logic again.
    if (n1 == null && n2 == null) {
        return 0;
    }
    if (n1 == null || n2 == null) {
        // Swap these around if you want 'null' at the other end.
        return n1 == null ? -1: 1;
    }
    return n1.compareTo(n2);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!