我正在尝试对JSONArray进行排序,但是我收到以下错误:
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:895)
at java.util.TimSort.mergeAt(TimSort.java:512)
at java.util.TimSort.mergeForceCollapse(TimSort.java:453)
at java.util.TimSort.sort(TimSort.java:250)
at java.util.Arrays.sort(Arrays.java:1523)
at java.util.Collections.sort(Collections.java:238)
这是我的代码:
private JSONArray SortJSONArray(String json) {
JSONArray sortedJsonArray = new JSONArray();
try {
JSONArray jsonArr = new JSONArray(json);
List<JSONObject> jsonValues = new ArrayList<JSONObject>();
for (int i = 0; i < jsonArr.length(); i++) {
jsonValues.add(jsonArr.getJSONObject(i));
}
Collections.sort(jsonValues, new Comparator<JSONObject>() {
private static final String KEY_NAME = "EUR";
@Override
public int compare(JSONObject a, JSONObject b) {
Double valA = 0.0;
Double valB = 0.0;
try {
valA = a.getDouble(KEY_NAME);
valB = b.getDouble(KEY_NAME);
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
}
if(valA < valB) {
return -1;
} else if( valB < valA) {
return 1;
} else {
return 0;
}
}
});
for (int i = 0; i < jsonArr.length(); i++) {
sortedJsonArray.put(jsonValues.get(i));
}
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
}
return sortedJsonArray;
}
答案 0 :(得分:3)
问题是a.getDouble(KEY_NAME)
或b.getDouble(KEY_NAME)
可能会引发异常。
如果a.getDouble(KEY_NAME)
引发异常且b.getDouble(KEY_NAME)
没有,b.getDouble(KEY_NAME)
永远不会被评估,valA
和valB
仍然是0.0
。
另一方面,如果您将a
与b
进行比较(即调用compare(b,a)
而不是compare(a,b)
,则会先评估b.getDouble(KEY_NAME)
a.getDouble(KEY_NAME)
会引发异常,因此valA
将0.0
而valB
会有其他值。
在这种情况下,compare(a,b)
将返回0
,compare(b,a)
将返回非零值(假设b.getDouble(KEY_NAME)
不返回0.0
),违反了Comparator
的合同。
在单独的try块中评估a.getDouble(KEY_NAME)
和b.getDouble(KEY_NAME)
将解决此问题。
try {
valA = a.getDouble(KEY_NAME);
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
}
try {
valB = b.getDouble(KEY_NAME);
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
}
return Double.compare(valA,valB);
答案 1 :(得分:0)
解决方法是在catch语句中返回一个值:
try {
valA = a.getDouble(KEY_NAME);
valB = b.getDouble(KEY_NAME);
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
return -10;
}
if(valA < valB) {
return -1;
} else if( valB < valA) {
return 1;
} else {
return 0;
}