2009-08-11 21 views
7

मैं कुछ कस्टम तुलनाकर्ता लिख ​​रहा हूं, और मैं चाहता हूं कि वे सूची के निचले हिस्से में नल आइटम को धक्का दें, भले ही मैं आरोही या अवरोही को क्रमबद्ध कर रहा हूं। इस के लिए एक अच्छी रणनीति या पैटर्न क्या है?निचले सामान्य को हल करने के लिए सामान्य सामान्य तरीका, भले ही?

बेतकल्लुफ़:

  • सीधे शब्दों में, अलग आरोही और उतरते तुलनाकारक बारे में जहां संभव
  • एक और वर्ग के लिए
  • प्रतिनिधि अशक्त हैंडलिंग कोड साझा करने, या तो यह स्पष्ट रूप से बुला
  • द्वारा एक एनपीई या फेंककर
  • एक आरोही ध्वज शामिल करें और को को नल के आसपास
  • पर नेविगेट करने के लिए सशर्त तर्क डालेंएक अशक्त-हैंडलिंग वर्ग

किसी भी अन्य रणनीतियों में

  • लपेटें नियमित तुलनाकारक? मैं विभिन्न दृष्टिकोणों के साथ किसी भी अनुभव, और विभिन्न रणनीतियों के लिए किसी भी नुकसान के बारे में सुनना चाहता हूं।

  • उत्तर

    5

    अंतिम विकल्प मुझे बहुत अपील करता है। तुलनाकर्ता एक साथ श्रृंखला के लिए वास्तव में महान हैं। विशेष रूप से आप ReverseComparator के साथ-साथ NullWrappingComparator लिखना चाहेंगे।


    संपादित करें: आपको इसे स्वयं लिखना नहीं है। आप Google Collections Library में Ordering वर्ग को देखें, तो आप इस और अन्य उपहार के सभी प्रकार मिल जाएगा :)


    संपादित करें: और अधिक विस्तार में जा रहे हैं दिखाने के लिए कि मैं क्या बारे में ReverseComparator मतलब ...

    चेतावनी का एक शब्द - ReverseComparator के कार्यान्वयन में, परिणाम को अस्वीकार करने के बजाय तर्कों के क्रम को उलट देता है, अन्यथा Integer.MIN_VALUE स्वयं को "उलट" दिया जाता है।

    तो यह क्रियान्वयन गलत (यह मानते हुए original उल्टा करने के लिए तुलनित्र है) है:

    public int compare(T x, T y) 
    { 
        return -original.compare(x, y); 
    } 
    

    लेकिन यह सही है:

    public int compare(T x, T y) 
    { 
        return original.compare(y, x); 
    } 
    

    कारण है कि हम हमेशा तुलना उल्टा करने के लिए चाहते हैं, लेकिन अगर original.compare(x, y)int.MIN_VALUE देता है, तो खराब तुलनाकर्ता भी वापसी int.MIN_VALUE, जो गलत है। यह मजेदार संपत्ति के कारण है int.MIN_VALUE == -int.MIN_VALUE

    +0

    तुलना के परिणाम को अस्वीकार करने के अलावा मैं आपके सभी उत्तर से सहमत हूं; अगर मुझे पता चला कि एक तुलनाकर्ता घटाव का उपयोग करके पूर्णांक तुलना को कार्यान्वित कर रहा था, तो मैं काफी दुखी हूं, क्योंकि उस विधि में इतनी सारी समस्याएं हैं। – jprete

    +1

    @jprete: मुझे लगता है कि आपने मुझे गलत समझा। मैं संपादित करूंगा। –

    +1

    मैं Google संग्रह 'ऑर्डरिंग क्लास के संदर्भ के कारण इस उत्तर को स्वीकार कर रहा हूं - मौजूदा सिद्ध कोड सबसे अच्छा समाधान है। Integer.MIN_VALUE के बारे में चेतावनी के लिए भी। लेकिन मैं नीचे @ dfa के कोड की बहुत सराहना करता हूं, और इच्छा करता हूं कि मैं दोनों उत्तरों को स्वीकार कर सकूं। –

    10

    मैं जॉन स्कीट से सहमत हूं (यह इतना आसान है :)।मैं लागू करने की कोशिश की एक बहुत ही सरल decorator:

    class NullComparators { 
    
        static <T> Comparator<T> atEnd(final Comparator<T> comparator) { 
         return new Comparator<T>() { 
    
          public int compare(T o1, T o2) { 
           if (o1 == null && o2 == null) { 
            return 0; 
           } 
    
           if (o1 == null) { 
            return 1; 
           } 
    
           if (o2 == null) { 
            return -1; 
           } 
    
           return comparator.compare(o1, o2); 
          } 
         }; 
        } 
    
        static <T> Comparator<T> atBeginning(final Comparator<T> comparator) { 
         return Collections.reverseOrder(atEnd(comparator)); 
        } 
    } 
    

    एक तुलनाकारी दिया:

    Comparator<String> wrapMe = new Comparator<String>() { 
         public int compare(String o1, String o2) { 
          return o1.compareTo(o2); 
         } 
    }; 
    

    और कुछ परीक्षण डेटा:

    :

    List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null); 
    

    आप अंत में nulls साथ सॉर्ट कर सकते हैं

    Collections.sort(strings, NullComparators.atEnd(wrapMe)); 
    
     
    [aaa, bbb, ccc, null, null, null] 
    

    या शुरुआत में:

    Collections.sort(strings, NullComparators.atBeginning(wrapMe)); 
    
     
    [null, null, null, ccc, bbb, aaa] 
    
    +3

    बहुत अच्छा! धन्यवाद। क्या 0 तर्क वापस करने का कोई कारण नहीं है यदि दोनों तर्क शून्य हैं? मुझे पता है कि शून्य व्यवहार गैर-शून्य व्यवहार की तरह नहीं है, और यह कहकर कि दो नल बराबर हैं, लेकिन यह कहने के लिए कम संदिग्ध है कि एक दूसरे से अधिक है? –

    +2

    @ करल: बिल्कुल जिस बिंदु को मैंने अभी आपके पोस्ट में बनाया है :) एक तुलनात्मक * * को वापस लौटा देना चाहिए या दो नल पारित होने पर अपवाद फेंकना चाहिए, अन्यथा यह इंटरफ़ेस अनुबंध का उल्लंघन नहीं कर रहा है। –

    5

    DFA के जवाब पर बाद - मैं क्या चाहते है कि nulls तरह गैर nulls के क्रम को प्रभावित किए बिना अंत में। तो मैं इस की तर्ज पर अधिक कुछ चाहते हैं: DFA को

    public class NullComparatorsTest extends TestCase { 
        Comparator<String> forward = new Comparator<String>() { 
                public int compare(String a, String b) { 
                 return a.compareTo(b); 
                } 
               }; 
    
        public void testIt() throws Exception { 
         List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null); 
         Collections.sort(strings, NullComparators.atEnd(forward)); 
         assertEquals("[aaa, bbb, ccc, null, null, null]", strings.toString()); 
         Collections.sort(strings, NullComparators.atBeginning(forward)); 
         assertEquals("[null, null, null, aaa, bbb, ccc]", strings.toString()); 
        } 
    } 
    
    public class NullComparators { 
        public static <T> Comparator<T> atEnd(final Comparator<T> comparator) { 
         return new Comparator<T>() { 
          public int compare(T a, T b) { 
           if (a == null && b == null) 
            return 0; 
           if (a == null) 
            return 1; 
           if (b == null) 
            return -1; 
           return comparator.compare(a, b); 
          } 
         }; 
        } 
    
        public static <T> Comparator<T> atBeginning(final Comparator<T> comparator) { 
         return new Comparator<T>() { 
          public int compare(T a, T b) { 
           if (a == null && b == null) 
            return 0; 
           if (a == null) 
            return -1; 
           if (b == null) 
            return 1; 
           return comparator.compare(a, b); 
          } 
         }; 
        } 
    } 
    

    पूर्ण क्रेडिट, हालांकि - यह सिर्फ अपने काम के एक मामूली संशोधन है।

    +1

    एक समस्या: दो नल की तुलना करते समय आप 0 वापस नहीं आते हैं। –

    +0

    धन्यवाद; सुधार के साथ संपादित किया गया। –

    2

    आप हमेशा कॉमन्स-संग्रह से NullComparator का उपयोग कर सकते हैं। यह Google संग्रह से अधिक लंबा रहा है।

    3

    जावा 8 में, आप Comparator.nullsLast और Comparator.nullsFirst स्थिर विधियों का उपयोग अधिक नल-अनुकूल तुलनाकर्ताओं के लिए कर सकते हैं। मान लीजिए आप एक Fruit वर्ग की तरह है निम्नलिखित:

    public class Fruit { 
        private final String name; 
        private final Integer size; 
    
        // Constructor and Getters 
    } 
    

    आप उनके आकार द्वारा फल का एक समूह को सॉर्ट और अंत में null रों डाल करना चाहते हैं:

    List<Fruit> fruits = asList(null, new Fruit("Orange", 25), new Fruit("Kiwi", 5)); 
    

    आप बस लिख सकते हैं:

    Collections.sort(fruits, Comparator.nullsLast(Comparator.comparingInt(Fruit::getSize))); 
    

    और परिणाम होगा:

    [Fruit{name='Kiwi', size=5}, Fruit{name='Orange', size=25}, null] 
    
    संबंधित मुद्दे