2008-09-24 18 views
20

जावा में, मैं एक कक्षा का उपयोग करता हूं जिसमें कुछ फ़ील्ड null हो सकते हैं। उदाहरण के लिए:तुलना में शून्य क्षेत्रों के साथ क्या करना है()?

class Foo { 
    String bar; 
    //.... 
} 

मैं इस वर्ग के लिए एक BarComparator लिखना चाहते हैं,

private static class BarComparator 
      implements Comparator<Foo> { 
     public int compare(final Foo o1, final Foo o2) 
     { 
      // Implementation goes here 
     } 
    } 

वहाँ तथ्य से निपटने के लिए o1 के किसी भी है कि, o2, o1.bar, o2.barnull हो सकता है एक मानक तरीका है , बिना घोंसले if ... else लिखने के बिना?

चीयर्स!

उत्तर

36

मुझे लगता है कि आप nulls सॉर्ट करने के लिए अधिक या कम एक छोटे से स्थिर विधि के साथ क्षेत्र compareTo विधि करने के लिए कॉल लपेट सकता है:

static <T extends Comparable<T>> int cp(T a, T b) { 
    return 
     a==null ? 
     (b==null ? 0 : Integer.MIN_VALUE) : 
     (b==null ? Integer.MAX_VALUE : a.compareTo(b)); 
} 

सरल उपयोग (एक से अधिक फ़ील्ड है सामान्य रूप से):

public int compare(final Foo o1, final Foo o2) { 
    return cp(o1.field, o2.field); 
} 
+1

विषय से मुझे पता है, लेकिन MIN/MAX_VALUE ओवर-/ 1 1 को प्राथमिकता देने का क्या कारण है? –

+6

देरी के जवाब के लिए खेद है। यह सुनिश्चित करना है कि हमारे पास त्रिभुज असमानता है। ए> बी> सी, a.compare के लिए (बी) + b.compareTo (सी) <= a.compareTo (सी)। ऐसा नहीं है कि कोई भी परवाह करेगा ... –

+0

अभी भी एक 'NullPointerException' फेंक सकता है, अगर ओ 1/ओ 2 शून्य है। आप ओ 1/ओ 2 को शून्य के साथ कैसे व्यवहार कर सकते हैं? ओपी का उल्लेख है: ओ 1, ओ 2, ओ 1.बार, ओ 2.बार शून्य हो सकता है। या एक तुलनित्र अनुबंध का वह हिस्सा है: नल की तुलना में एनपीई फेंकना चाहिए? – Daniel

1

ऐसा लगता है कि ऐसा करने का कोई तरीका नहीं है, लेकिन फिर भी कोड इतना लंबा नहीं है।

0

मुझे लगता है कि जल्दी वापसी बयान आईएफएस

जैसे की बहुत सारी करने के लिए अन्य विकल्प होगा

if(o1==null) return x; 
if(o2==null) return x; 
if(o1.getBar()==null) return x; 
if(o2.getBar()==null) return x; 

// No null checks needed from this point. 
6

यह इस बात पर निर्भर करता है कि क्या आप एक शून्य प्रविष्टि को तुलनात्मक मूल्य के वैध स्ट्रिंग मान मानते हैं या नहीं। शून्य < या> "सेब" है। एकमात्र चीज जो मैं निश्चित रूप से कह सकता हूं वह है कि शून्य == शून्य। यदि आप परिभाषित कर सकते हैं कि ऑर्डर में शून्य कहाँ फिट बैठता है तो आप कोड को उचित रूप से लिख सकते हैं।

इस मामले में मैं एक NullPointerExcpetion या IllegalArgumentException फेंकना चुन सकता हूं और इसे पहले स्थान की तुलना में उच्च स्तर पर नल को संभालने का प्रयास कर सकता हूं।

+0

मुझे यह जवाब पसंद है। धन्यवाद! – Burkhard

2

यहां महत्वपूर्ण बात यह है कि आप कैसे नल के इलाज के लिए काम करना चाहते हैं। कुछ विकल्प हैं: ए) मान लें कि नल क्रमबद्ध क्रम में अन्य सभी वस्तुओं से पहले आते हैं b) मान लें कि नल सभी क्रमिक क्रम में अन्य सभी ऑब्जेक्ट्स के बाद आते हैं c) कुछ डिफ़ॉल्ट मान के समतुल्य शून्य के साथ व्यवहार करें डी) त्रुटि की स्थिति के रूप में नल का इलाज करें। आप जो भी चुनते हैं वह पूरी तरह से उस एप्लिकेशन पर निर्भर करेगा जिस पर आप काम कर रहे हैं।

पाठ्यक्रम के आखिरी मामले में आप एक अपवाद फेंक देते हैं। दूसरों के लिए आपको एक चार-तरफा की आवश्यकता है यदि/अन्य मामले (कोडिंग के लगभग तीन मिनट जो आपने काम किया है, जो आप परिणाम चाहते हैं)।

2

यदि आप Google संग्रह का उपयोग कर रहे हैं, तो आपको Comparators क्लास सहायक मिल सकता है। अगर संग्रह में सबसे महान या कम से कम तत्वों के रूप में नल को ऑर्डर करने के लिए सहायक तरीके हैं। कोड की मात्रा को कम करने में सहायता के लिए आप compound comparators का उपयोग कर सकते हैं।

8

उत्तर के लिए धन्यवाद! सामान्य विधि और Google तुलनात्मक दिलचस्प लगते हैं।

और मैंने पाया है कि Apache Commons Collections में एक NullComparator (जो हम वर्तमान में उपयोग कर रहे हैं):

private static class BarComparator 
     implements Comparator<Foo> 
{ 
    public int compare(final Foo o1, final Foo o2) 
    { 
     // o1.bar & o2.bar nulleness is taken care of by the NullComparator. 
     // Easy to extend to more fields. 
     return NULL_COMPARATOR.compare(o1.bar, o2.bar); 
    } 

    private final static NullComparator NULL_COMPARATOR = 
              new NullComparator(false); 
} 

नोट: मैं इसे बात करने के लिए रखने के लिए यहां bar क्षेत्र पर जोर दिया।

+1

ऐसा लगता है कि जावाडॉक्स का लिंक मर चुका है। यह अब http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html पर स्थित है। – JBert

1

आपको नल कॉम्पैक्टर का उपयोग करने के तरीके का उपयोग नहीं करना चाहिए - आप प्रत्येक तुलना ऑपरेशन के लिए कक्षा का एक नया उदाहरण बना रहे हैं, और यदि उदा। आप 1000 प्रविष्टियों वाली एक सूची को सॉर्ट कर रहे हैं, जो 1000 * लॉग 2 (1000) ऑब्जेक्ट्स होगी जो पूरी तरह से अनावश्यक हैं। यह जल्दी से समस्याग्रस्त हो सकता है।

या तो यह उपवर्ग, या यह प्रतिनिधि, या बस अपने खुद के अशक्त जांच को लागू - सचमुच यह इतना जटिल नहीं है:

private static class BarComparator 
     implements Comparator<Foo> { 
    private NullComparator delegate = new NullComparator(false); 

    public int compare(final Foo o1, final Foo o2) 
    { 
     return delegate.compare(o1.bar, o2.bar); 
    } 
} 
+0

आप सही हैं, नलकंपेटर एक निजी स्थैतिक क्षेत्र होना चाहिए। मैंने इसे शून्य तरीके पर ध्यान केंद्रित करने के लिए उदाहरण में लिखा था। –

3

आप इसके लिए अपने तुलनाकारी लिख सकते हैं। मान लें कि आपके पास स्ट्रिंग नाम वाले निजी व्यक्ति के रूप में एक क्लास व्यक्ति है। फ़ील्ड नाम तक पहुंचने के लिए getName() और setName() विधि। नीचे वर्ग व्यक्ति के लिए तुलनात्मक है।

Collections.sort(list, new Comparator<Person>() { 
     @Override 
     public int compare(Person a, Person b) { 
      if (a == null) { 
       if (b == null) { 
        return 0; 
       } 
       return -1; 
      } else if (b == null) { 
       return 1; 
      } 
      return a.getName().compareTo(b.getName()); 
     } 
    }); 

अद्यतन:

जावा 8 के रूप में आप एपीआई नीचे का उपयोग कर सकते सूची के लिए।

// Push nulls at the end of List 
Collections.sort(subjects1, Comparator.nullsLast(String::compareTo)); 

// Push nulls at the beginning of List 
Collections.sort(subjects1, Comparator.nullsFirst(String::compareTo)); 
2

वहाँ भी वर्ग org.springframework.util.comparator.NullSafeComparator स्प्रिंग फ्रेमवर्क का उपयोग कर सकते है।

उदाहरण (जावा 8):

SortedSet<Foo> foos = new TreeSet<>((o1, o2) -> { 
     return new NullSafeComparator<>(String::compareTo, true).compare(o1.getBar(), o2.getBar()); 
    }); 

    foos.add(new Foo(null)); 
    foos.add(new Foo("zzz")); 
    foos.add(new Foo("aaa")); 

    foos.stream().forEach(System.out::println); 

यह प्रिंट होगा:

Foo{bar='null'} 
Foo{bar='aaa'} 
Foo{bar='zzz'} 
0

एक POJO.My जवाब के रूप में ग्राहक को ध्यान में रखते होगा:

Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId())); 

या

Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo)); 
संबंधित मुद्दे