2014-10-14 10 views
5

यह एक सरल प्रश्न हो सकता है, लेकिन मैं यह स्पष्ट रूप से समझने के लिए चाहते हैं ...जावा 8 तुलनाकारी nullsFirst naturalOrder उलझन

मैं इस तरह एक कोड है:

public final class Persona 
{ 
    private final int id; 
    private final String name 
    public Persona(final int id,final String name) 
    { 
     this.id = id; 
     this.name = name; 
    } 
    public int getId(){return id;}  
    public String getName(){return name;}  
    @Override 
    public String toString(){return "Persona{" + "id=" + id + ", name=" + name+'}';}  
} 

और मैं इस कोड का परीक्षण कर रहा हूँ :

Persona{id=5, name=null} 
Persona{id=4, name=Chinga} 
Persona{id=1, name=Cristian} 
Persona{id=3, name=Cristina} 
Persona{id=2, name=Guadalupe} 
:

import static java.util.Comparator.*; 
private void nullsFirstTesting() 
{    
    final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst(naturalOrder())); 
    final List<Persona>persons = Arrays.asList(new Persona(1,"Cristian"),new Persona(2,"Guadalupe"),new Persona(3,"Cristina"),new Persona(4,"Chinga"),new Persona(5,null)); 
    persons 
      .stream() 
      .sorted(comparator) 
      .forEach(System.out::println);       
} 

यह निम्न परिणाम दिखाता है

ये परिणाम मेरे साथ ठीक हैं लेकिन मुझे समझ में समस्या है।

जब मैं new Persona(5,null) वस्तु पर ध्यान न दें और मैं तुलनित्र पारित:

final Comparator<Persona>comparator = comparing(Persona::getName); 

यह एक आकर्षण की तरह काम करता है। मेरा सॉर्टिंग natural order of name property है। समस्या तब उत्पन्न होती है जब मैं name=null के साथ ऑब्जेक्ट जोड़ता हूं, मैंने सोचा कि मुझे इस तरह के तुलनित्र की आवश्यकता होगी।

final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst()); 

मेरे बारे में सोचा था गलत: "ठीक है, जब नाम में गैर-शून्य है, वे natural order of name में सिर्फ पिछले तुलनित्र की तरह हल कर रहे हैं, और अगर वे null हैं वे पहली बार मेरी गैर होगा लेकिन शून्य नाम अभी भी प्राकृतिक क्रम में क्रमबद्ध किए जाएंगे "।

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

final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst(naturalOrder())); 

मैं nullsFirst पैरामीटर समझ में नहीं आता। मैंने सोचा कि natural order of name स्पष्ट रूप से [डिफ़ॉल्ट] null मानों को संभालेगा।

लेकिन डॉक्स कहते हैं:

एक अशक्त के अनुकूल है तुलनित्र कि null समझता है रिटर्न से गैर-शून्य कम होने के लिए। जब null दोनों होते हैं, तो उन्हें बराबर माना जाता है। यदि दोनों गैर-शून्य हैं, तो आदेश निर्धारित करने के लिए निर्दिष्ट Comparator का उपयोग किया जाता है। यदि निर्दिष्ट तुलनित्र null, है तो लौटा हुआ तुलनित्र सभी गैर-शून्य मानों को बराबर मानता है।

यह पंक्ति: "यदि दोनों गैर-शून्य हैं, तो निर्दिष्ट Comparator आदेश निर्धारित करने के लिए उपयोग किया जाता है।"

मैं उलझन में हूं कि कब और कैसे प्राकृतिक आदेश स्पष्ट रूप से सेट किया जाना चाहिए या जब उनका अनुमान लगाया जाए।

+3

नोट उत्पादन का उत्पादन * "अगर निर्दिष्ट तुलनित्र 'शून्य' है, तो लौटा तुलनित्र सभी गैर-शून्य मानों को बराबर मानता है। "* दूसरे शब्दों में, आप 'nullsFirst (null)' कर सकते हैं; हालांकि यह नॉन-नल को सॉर्ट किए बिना मोर्चे पर सामने की ओर जाता है। डॉक्टर वास्तव में इसे अच्छी तरह से समझाता है। – Radiodef

+0

@chiperotiz तो आप अंततः इसे कैसे हल किया? क्या आप पहले नल और फिर प्राकृतिक आदेश से सॉर्ट करने में सक्षम थे? – Unheilig

+1

हां इस कोड का उपयोग करके 'अंतिम तुलनाकर्ता तुलनित्र = तुलना करना (पर्सना :: getName, nullsFirst (प्राकृतिक ऑर्डर())); – chiperortiz

उत्तर

17

"प्राकृतिक आदेश" तुलनित्र, जब आप comparing का उपयोग केवल एक पैरामीटर के साथ करते हैं, तो नल को संभालता है। (मुझे यकीन नहीं है कि आपको यह विचार कहां मिला है।) एक Comparable वर्ग के "प्राकृतिक व्यवस्था" compareTo() विधि है, जो इस तरह प्रयोग किया जाता है द्वारा परिभाषित किया गया है:

obj1.compareTo(obj2) 

जाहिर है इस अगर obj1 रिक्त है काम नहीं करेगा; String के लिए, यह obj2 का अपवाद भी फेंक देगा।

naturalOrder() विधि Comparator देता है जो दो वस्तुओं की तुलना करता है। javadoc स्पष्ट रूप से कहता है कि शून्य से तुलना करते समय यह तुलनित्र NullPointerException फेंकता है।

nullsFirst() विधि (और nullsLast() इसी तरह) मूल रूप से एक नया Comparator करने के लिए एक Comparator बदल देती है। आप एक तुलनित्र डालते हैं जो अपवाद को फेंक सकता है अगर यह शून्य की तुलना करने की कोशिश करता है, और यह एक नया तुलनित्र थूकता है जो उसी तरह काम करता है सिवाय इसके कि यह शून्य तर्कों को अनुमति देता है। इसलिए आपको nullsFirst पर पैरामीटर की आवश्यकता है - क्योंकि यह मौजूदा तुलनित्र के शीर्ष पर एक नया तुलनित्र बनाता है, और आप इसे बताते हैं कि मौजूदा तुलनित्र क्या है।

तो यदि आप पैरामीटर छोड़ देते हैं तो यह आपको प्राकृतिक आदेश क्यों नहीं देता है? क्योंकि उन्होंने इसे इस तरह परिभाषित नहीं किया था। nullsFirst एक पैरामीटर लेने के लिए javadoc में परिभाषित किया गया है:

static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) 

मुझे लगता है कि अगर डिजाइनरों करना चाहता था, वे एक अधिभार है कि कोई पैरामीटर लेता है जोड़ सकते हैं:

static <T> Comparator<T> nullsFirst() // note: not legal 

है कि एक ही होगा nullsFirst(naturalOrder()) का उपयोग करने के रूप में। लेकिन उन्होंने नहीं किया, तो आप इसका इस्तेमाल इस तरह नहीं कर सकते।

+0

हैलो एजेबी मैंने कभी नहीं सोचा था कि एकमात्र पैरामीटर तुलनित्र नल को संभालेगा .. मैंने बस nullsFirst () विधि पहले नल को रखेगी और गैर-नल को प्राकृतिक क्रम में भी क्रमबद्ध किया जाएगा ... लेकिन जैसा कि आपने कहा था कि 'स्थिर तुलनाकर्ता nullsFirst() // नोट: कानूनी' सरल कानूनी नहीं है। मैंने सोचा कि अच्छा होगा जैसा आपने कहा था कि बिना किसी पैरामीटर के पैरामीटर प्राकृतिक ऑर्डर() डिफ़ॉल्ट रूप से होना चाहिए .. धन्यवाद। – chiperortiz

11

प्रयास करें:

final Comparator<Persona> comparator = 
    comparing(Persona::getName, nullsFirst(naturalOrder())); 
1

मैं नाम और आईडी के साथ छात्र के साथ कर्मचारी की एक सूची है ..

import java.util.ArrayList; 
import java.util.Iterator; 

import java.util.List; 
import java.util.Comparator; 

public class TestClass { 

    public static void main(String[] args) { 

     Student s1 = new Student("1","Nikhil"); 
     Student s2 = new Student("1","*"); 
     Student s3 = new Student("1",null); 
     Student s11 = new Student("2","Nikhil"); 
     Student s12 = new Student("2","*"); 
     Student s13 = new Student("2",null); 
     List<Student> list = new ArrayList<Student>(); 
     list.add(s1); 
     list.add(s2); 
     list.add(s3); 
     list.add(s11); 
     list.add(s12); 
     list.add(s13); 

     list.sort(Comparator.comparing(Student::getName,Comparator.nullsLast(Comparator.naturalOrder()))); 

     for (Iterator iterator = list.iterator(); iterator.hasNext();) { 
      Student student = (Student) iterator.next(); 
      System.out.println(student); 
     } 


    } 

} 

रूप

Student [name=*, id=1] 
Student [name=*, id=2] 
Student [name=Nikhil, id=1] 
Student [name=Nikhil, id=2] 
Student [name=null, id=1] 
Student [name=null, id=2]