From the above links,i hope i'm following the answers which are accepted.But still i m 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);