2013-10-11 6 views
36

नमस्ते नीचे मेरे तुलनित्र की मेरी तुलना विधि है। मुझे यकीन नहीं है कि क्या गलत है। मैंने स्टैक ओवरफ्लो पर अन्य समान शीर्षक वाले प्रश्नों और उत्तरों को देखा लेकिन यह सुनिश्चित नहीं है कि मेरी विधि में क्या गलत है लेकिन मैं java.lang.IllegalArgumentException प्राप्त कर रहा हूं: तुलना विधि अपने सामान्य अनुबंध का उल्लंघन करती है!java.lang.IleglegalArgumentException: तुलना विधि अपने सामान्य अनुबंध का उल्लंघन करती है

किसी भी मदद की बहुत सराहना की जाएगी

public int compare(Node o1, Node o2) 
{ 
    HashMap<Integer,Integer> childMap = orderMap.get(parentID); 
    if(childMap != null && childMap.containsKey(o1.getID()) && 
          childMap.containsKey(o2.getID())) 
    { 
     int order1 = childMap.get(o1.getID()); 
     int order2 = childMap.get(o2.getID()); 

     if(order1<order2) 
      return -1; 
     else if(order1>order2) 
      return 1; 
     else 
      return 0; 
    } 
    else 
     return 0; 
} 

अपवाद जोड़ना मैं हो रही है

java.lang.IllegalArgumentException: Comparison method violates its general contract! 
at java.util.TimSort.mergeLo(TimSort.java:747) 
at java.util.TimSort.mergeAt(TimSort.java:483) 
at java.util.TimSort.mergeCollapse(TimSort.java:410) 
at java.util.TimSort.sort(TimSort.java:214) 
at java.util.TimSort.sort(TimSort.java:173) 
at java.util.Arrays.sort(Arrays.java:659) 
at java.util.Collections.sort(Collections.java:217) 
+0

आपको किस लाइन पर अपवाद मिलता है? –

+0

@tieTYT मुझे लगता है कि अपवाद को उस संग्रह के भीतर से फेंक दिया जा रहा है जिसे वह 'तुलनाकर्ता' के रूप में पास कर रहा है। यह तुलनित्र वास्तव में अस्थिर दिखता है, क्योंकि * 'orderMap [parentID]' * में कोई भी संशोधन या 'childMap' में निर्दिष्ट ऑर्डरिंग आइटम को चारों ओर ले जायेगा। – chrylis

+0

'parentId' प्रकार क्या है? क्या आप मानचित्र के भीतर हैश मैप संग्रहीत कर रहे हैं? –

उत्तर

49

आपका compare() विधि नहीं सकर्मक है। यदि A == B और B == C, तो AC के बराबर होना चाहिए।

अब इस मामले पर विचार:

A, B, और C लिए, मान लीजिए containsKey() विधि इन परिणामों लौट:

  • childMap.containsKey(A.getID()) रिटर्न true
  • childMap.containsKey(B.getID()) रिटर्न false
  • childMap.containsKey(C.getID()) रिटर्न true

इसके अलावा, A.getId() के लिए ऑर्डर पर विचार करें! = B.getId()

तो,

  1. A और B0 वापसी होगी, के रूप में बाहरी if हालत false हो जाएगा =>A == B
  2. B और C0 वापसी होगी, बाहरी if हालत हो जाएगा false =>B == C
  3. के रूप में

लेकिन, और C, if ब्लॉक के अंदर आपके परीक्षण के आधार पर -1, या 1 वापस कर सकता है। तो, A != C। यह पारगमन सिद्धांत का उल्लंघन करता है।

मुझे लगता है कि आपको अपने else ब्लॉक के अंदर कुछ शर्त जोड़नी चाहिए, जो if ब्लॉक में आप कैसे करते हैं, इस तरह की जांच करता है।

3

मुझे लगता है कि समस्या आपके डिफ़ॉल्ट मामले में है। नोड्स ए, बी, और सी के सेट पर विचार करें, जहां आईडी 'a', 'b', और 'c' हैं।आगे देखिए कि आपके childMap है, जो रिश्तेदार आदेश में जानकारी शामिल है कि, निम्नलिखित सामग्री है: यदि आप ए और बी पर अपने compare विधि चलाते हैं

{ 'a' => 1, 'c' => 3 } 

अब, आप 0 लौटने के लिए, यह दर्शाता है कि ए और बी के बराबर हैं। इसके अलावा, यदि आप बी और सी की तुलना करते हैं, तो भी आप 0 लौटते हैं। हालांकि, यदि आप ए और सी की तुलना करते हैं, तो आप -1 लौटते हैं, जो दर्शाता है कि ए छोटा है। ,

The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0 .

Finally, the implementor must ensure that compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z .

आप "आइटम जो सौंपा एक आदेश की जरूरत नहीं है" मूल्य "कहीं बीच में थोड़ा" के रूप में इलाज नहीं कर सकते हैं के बाद से छँटाई एल्गोरिदम पता नहीं है: यह the Comparator contract की संक्रामिता संपत्ति का उल्लंघन करती है उन्हें कहां रखना है। यदि आप इस दृष्टिकोण के साथ रहना चाहते हैं, तो उस स्थिति में जहां मानचित्र में मान मौजूद नहीं है, आपको ऑर्डरिंग नंबर होने के लिए एक निश्चित मान असाइन करना होगा; 0 या MIN_INT जैसी कुछ उचित विकल्प है (लेकिन किसी भी विकल्प को compare के लिए जावाडोक में दस्तावेज करने की आवश्यकता है!)।

संबंधित मुद्दे