Java 在android中排序时如何避免IllegalArgumentException

Java 在android中排序时如何避免IllegalArgumentException,java,android,android-4.2-jelly-bean,Java,Android,Android 4.2 Jelly Bean,发行 从上面的链接中,我希望我遵循的答案是被接受的。但我还是得到了例外。我正在使用Java6 代码: public class GenericComparator implements Comparator<User> { private static final String TAG = "java.util.Comparator.GenericComparator"; EnumComparatorObjectType mType; public GenericComparat

发行

从上面的链接中,我希望我遵循的答案是被接受的。但我还是得到了例外。我正在使用Java6

代码:

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;
}

}
公共类GenericComparator实现Comparator{
私有静态最终字符串TAG=“java.util.Comparator.GenericComparator”;
EnumComparatorObject类型mType;
公共GenericComparator(EnumComparatorObjectType paramType){
mType=paramType;
}
@凌驾
公共int比较(用户user1、用户user2){
if(user1==null&&user2==null)
返回0;
试一试{
if(mType==enumparatorobjecttype.ENUM\u OBJECT\u ADDRESS\u BOOK\u条目){
字符串name1=user1.getUsername();
字符串name2=user2.getUsername();
返回name1.compareTignoreCase(name2);
}else if(mType==EnumComparatorObjectType.ENUM\u对象\u存在){
EnumPresence p1=user1.getState();
EnumPresence p2=user2.getState();
返回p1.compareTo(p2);
}
}捕获(例外e){
Logger.i(标记,e.getMessage(),e);
}
返回0;
}
}
堆栈跟踪:

java.lang.IllegalArgumentException:比较方法违反了它的一般约定!
位于java.util.TimSort.mergeHi(TimSort.java:864)
位于java.util.TimSort.mergeAt(TimSort.java:481)
位于java.util.TimSort.mergeForceCollapse(TimSort.java:422)
位于java.util.TimSort.sort(TimSort.java:219)
位于java.util.TimSort.sort(TimSort.java:169)
位于java.util.Arrays.sort(Arrays.java:2038)
位于java.util.Collections.sort(Collections.java:1891)
位于com.sample.app.adapters.BuddyListAdapter.filerContacts(BuddyListAdapter.java:144)
位于com.sample.app.adapters.BuddyListAdapter.notifyDataSetChanged(BuddyListAdapter.java:126)
在com.sample.app.HomeActivity$2.onReceive上(HomeActivity.java:325)
在android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:763)中
... 9更多

您已经处理了两个条目均为
null
的情况,但没有处理其中一个为
null
而另一个不为null的情况。您使用了
catch(Exception…
,它也捕获
NullPointerException
,然后返回0,这一事实隐藏了问题。这意味着与
null
比较的任何对象返回0(意味着
null
和一个对象相等),但非null项通常会进行比较。根据这个逻辑,你可以得到一个[1]==a[2],一个[1]==a[3],但是一个[2]!=a[3]。这显然是错误的,因为它不允许对对象进行正确排序。这就是异常消息“Comparison method违反了它的一般约定”试图表达的意思。所以我建议不要捕捉异常

我建议尝试以下方法:

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);
}
如果您首先要按状态进行比较,然后按名称进行比较,则可以去掉
mType
,第二部分(在检查
null
)将变成:

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);

在排序过程中,两个用户的状态是否发生变化?如果user1>user2==true,那么当我的好友状态发生变化时,我会收到user2通知,并首先按字母顺序排序,然后按状态进行排序。对于通知的每个新状态,此过程都会继续。排序(mUsers,新的GenericComparator(EnumComparatorObjectType.ENUM_OBJECT_ADDRESS_BOOK_ENTRY));排序(mUsers,新的GenericComparator(EnumComparatorObjectType.ENUM_OBJECT_PRESENCE));使用两个不同的比较器可以解决我的问题?如果我是你,我会先比较getState(),如果结果等于0,我会比较getUsername()。否则,返回getState()结果。@Aprian相同的逻辑适用于前面提到的链接2,其中time=presence,vollot=username。你的意思是相同的吗?@421你删除了
try{…}catch…
部分了吗?它需要删除,因为它隐藏了问题。如果您在比较时确实遇到异常,请发布该异常的堆栈跟踪。是的,我在前面删除了try catch。我更新了您的最新答案。感谢所示的代码更正。错误还在于处理数组列表,它会随着状态的变化而不断变化。现在又创建了一个临时数组列表来对列表进行排序。我现在看不到错误。