使用自定义比较器会导致顺序不一致
Using custom comparator results in inconsistent ordering
我正在使用一个 Android 应用程序,我想以某种方式打印出 HashMap 的键和值。假设以下是 HashMap 的内容:
11: 000010
12: 102643
24: 877
3: 990000
h: 6008770000
m: 0800
我想打印出 HashMap 键和值,这样带有字母的键应首先按字母顺序打印,然后按升序打印数字键:
h: 6008770000
m: 0800
3: 990000
11: 000010
12: 102643
24: 877
我现在正在做的是:
获取键集并将其保存到ArrayList
使用比较器对 ArrayList 进行排序
使用排序列表打印出地图中的值
这是我的代码:
List<String> keyList = new ArrayList<>(requestMap.keySet());
Collections.sort((keyList), comparator);
for(String key : keyList) {
Log.d(key, requestMap.get(key));
}
Comparator<String> comparator = (o1, o2) -> {
if (o1 == null) return -1;
else if (o2 == null) return 1;
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
} else {
return o1.compareTo(o2);
}
};
目前为止一切正常,但在某些情况下我没有得到想要的订单。例如,对于特定的地图,我总是得到以下结果:
3: 005000
4: 000000058985
12: 095508
22: 022
h: 6008770000
m: 0221
11: 000004
13: 0120
24: 877
25: 00
35: 77690088000000131D20077100000F
37: QWERTY123456
41: 00000003
42: 100000004000000
48: 456789123451 0000050201
60: 000001
61: 0201020000000045000000000300000000000015000102000000049770000000049770000000001659
我制作比较器的想法是字母字符串应该首先排序,然后是数字字符串,但现在我怀疑我的比较器逻辑是否正确。谁能指出我正确的方向?
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
所以只处理了都是数字的情况
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
这是第一个有非数字的情况。这是 return -1 即使第二个没有数字。当两者都有非数字时,我们应该进行比较。
} else {
return o1.compareTo(o2);
这是第一个是数字的情况,所以不想比较。因为我们已经排除了两者都是数字,所以第二个必须是非数字(尽管我们不应该比较)。
}
所以,看来您确实想删除 !
!
您可能还应该涵盖所有情况。要么有一个条件,你是否应该覆盖比较案例
!TextUtils.isDigitsOnly(o1) && !TextUtils.isDigitsOnly(o2)
或嵌套
if (TextUtils.isDigitsOnly(o1)) {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
} else {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
}
我正在使用一个 Android 应用程序,我想以某种方式打印出 HashMap 的键和值。假设以下是 HashMap 的内容:
11: 000010
12: 102643
24: 877
3: 990000
h: 6008770000
m: 0800
我想打印出 HashMap 键和值,这样带有字母的键应首先按字母顺序打印,然后按升序打印数字键:
h: 6008770000
m: 0800
3: 990000
11: 000010
12: 102643
24: 877
我现在正在做的是:
获取键集并将其保存到ArrayList
使用比较器对 ArrayList 进行排序
使用排序列表打印出地图中的值
这是我的代码:
List<String> keyList = new ArrayList<>(requestMap.keySet());
Collections.sort((keyList), comparator);
for(String key : keyList) {
Log.d(key, requestMap.get(key));
}
Comparator<String> comparator = (o1, o2) -> {
if (o1 == null) return -1;
else if (o2 == null) return 1;
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
} else {
return o1.compareTo(o2);
}
};
目前为止一切正常,但在某些情况下我没有得到想要的订单。例如,对于特定的地图,我总是得到以下结果:
3: 005000
4: 000000058985
12: 095508
22: 022
h: 6008770000
m: 0221
11: 000004
13: 0120
24: 877
25: 00
35: 77690088000000131D20077100000F
37: QWERTY123456
41: 00000003
42: 100000004000000
48: 456789123451 0000050201
60: 000001
61: 0201020000000045000000000300000000000015000102000000049770000000049770000000001659
我制作比较器的想法是字母字符串应该首先排序,然后是数字字符串,但现在我怀疑我的比较器逻辑是否正确。谁能指出我正确的方向?
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
所以只处理了都是数字的情况
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
这是第一个有非数字的情况。这是 return -1 即使第二个没有数字。当两者都有非数字时,我们应该进行比较。
} else {
return o1.compareTo(o2);
这是第一个是数字的情况,所以不想比较。因为我们已经排除了两者都是数字,所以第二个必须是非数字(尽管我们不应该比较)。
}
所以,看来您确实想删除 !
!
您可能还应该涵盖所有情况。要么有一个条件,你是否应该覆盖比较案例
!TextUtils.isDigitsOnly(o1) && !TextUtils.isDigitsOnly(o2)
或嵌套
if (TextUtils.isDigitsOnly(o1)) {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
} else {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
}