2017-11-27 8 views
2

私はJSONArrayをソートするためにしようとしているが、私は次のエラーを取得しています:ここで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

https://developer.android.com/reference/org/json/JSONObject.html#getDouble(java.lang.String) は、それが投げることができるようだが、それはnullを返します言っていない – TomSelleck

+0

@エランあなたはそれを分解したと思う - キャッチステートメントの-10を返すことはそれを修正するようだ。 – TomSelleck

答えて

3

問題がa.getDouble(KEY_NAME)またはb.getDouble(KEY_NAME)のいずれかが例外を投げることができるということです。

a.getDouble(KEY_NAME)が例外をスローし、b.getDouble(KEY_NAME)は、b.getDouble(KEY_NAME)が評価されることはありませんしないとvalAvalB両方が0.0残っている場合。

あなたはabを比較する一方、逆の順序である(すなわちcompare(b,a)の代わりcompare(a,b)を呼び出し、a.getDouble(KEY_NAME)が例外をスローする前b.getDouble(KEY_NAME)が評価されますので、valA0.0valBになります他のいくつかの値を持つことになります。

その場合

compare(a,b)Comparatorの契約に違反している、(0.0を返さないb.getDouble(KEY_NAME)を想定)0戻り、compare(b,a)は、非ゼロ値を返す。

別の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); 
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; 
    } 
+0

これは良い回避策ではありません。 'a.getDouble(KEY_NAME)'が例外をスローすると、 'compare(a、b)'と 'compare(b、a)'はどちらも負の値(-10)を返し、Comparatorの契約に違反します。 – Eran

関連する問題