简体   繁体   中英

how to avoid IllegalArgumentException while sorting in android

ISSUE link 1 link 2 link 3

From the above links,i hope i'm following the answers which are accepted.But still im getting the exception. I'm using Java 6.

code :

public class GenericComparator implements Comparator<User> {

private static final String TAG = "java.util.Comparator.GenericComparator";
EnumComparatorObjectType mType;

public GenericComparator(EnumComparatorObjectType paramType) {

    mType = paramType;
}

@Override
public int compare(User user1, User user2) {

    if (user1 == null && user2 == null)
        return 0;
    try {
        if (mType == EnumComparatorObjectType.ENUM_OBJECT_ADDRESS_BOOK_ENTRY) {
            String name1 = user1.getUsername();
            String name2 = user2.getUsername();
            return name1.compareToIgnoreCase(name2);
        } else if (mType == EnumComparatorObjectType.ENUM_OBJECT_PRESENCE) {
            EnumPresence p1 = user1.getState();
            EnumPresence p2 = user2.getState();
            return p1.compareTo(p2);
        }
    } catch (Exception e) {
        Logger.i(TAG, e.getMessage(), e);

    }
    return 0;
}

}

Stack trace :

java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(TimSort.java:864) at java.util.TimSort.mergeAt(TimSort.java:481) at java.util.TimSort.mergeForceCollapse(TimSort.java:422) at java.util.TimSort.sort(TimSort.java:219) at java.util.TimSort.sort(TimSort.java:169) at java.util.Arrays.sort(Arrays.java:2038) at java.util.Collections.sort(Collections.java:1891) at com.sample.app.adapters.BuddyListAdapter.filerContacts(BuddyListAdapter.java:144) at com.sample.app.adapters.BuddyListAdapter.notifyDataSetChanged(BuddyListAdapter.java:126) at com.sample.app.HomeActivity$2.onReceive(HomeActivity.java:325) at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:763) ... 9 more

You have taken care of the case that both entries are null , but not the case that one is null and the other is not. The problem was hidden by the fact that you used catch (Exception ...) , which also catches NullPointerException , and then return 0. That means any object compared to null returns 0 (meaning null and an object are equal), but non-null entries are compared normally. According to this logic, you coult get a[1] == a[2], and a[1] == a[3], but a[2] != a[3]. This is clearly wrong as it wouldn't allow objects to be sorted correctly. This is what the exception message "Comparison method violates its general contract" is trying to say. So I suggest to not catch Exception .

I suggest to try the following:

if (user1 == null || user2 == null) {
    if (user1 == user2) {
        // both are null
        return 0;
    } else if (user1 == null) {
        return -1;
    }
    // user2 is null
    return 1;
}
if (mType == EnumComparatorObjectType.ENUM_OBJECT_ADDRESS_BOOK_ENTRY) {
    String name1 = user1.getUsername();
    String name2 = user2.getUsername();
    return name1.compareToIgnoreCase(name2);
} else if (mType == EnumComparatorObjectType.ENUM_OBJECT_PRESENCE) {
    EnumPresence p1 = user1.getState();
    EnumPresence p2 = user2.getState();
    return p1.compareTo(p2);
} else {
    throw IllegalArgumentException("Unsupported type: " + mType);
}

If you first want to compare by state and then by name, you could get rid of mType , and the second part (after checking for null ) would become:

EnumPresence p1 = user1.getState();
EnumPresence p2 = user2.getState();
int comp = p1.compareTo(p2);
if (comp != 0) {
    return comp;
}
String name1 = user1.getUsername();
String name2 = user2.getUsername();
return name1.compareToIgnoreCase(name2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM