2010-02-28 18 views
36

मैंने जेनिक्स का उपयोग करके जावा में एक लिंक्ड सूची बनाई है, और अब मैं सूची में सभी तत्वों को फिर से चलाने में सक्षम होना चाहता हूं। सी # में सूची में निहित तत्वों की सूची के दौरान लिंक किए गए सूची के अंदर yield return का उपयोग किया जाएगा।जावा में यील्ड रिटर्न

मैं उपरोक्त का जावा संस्करण बनाने के बारे में कैसे जाउंगा जहां मैं लिंक की गई सूची में मौजूद सभी वस्तुओं पर पुन: प्रयास कर सकता हूं?

मैं आला

LinkedList<something> authors = new LinkedList<something>(); 
for (Iterator<something> i = authors.Values ; i.HasNext()) 
     doSomethingWith(i.Value); 

कोड लिखने के लिए सक्षम होने के लिए देख रहा हूँ और सोच रहा था कि मूल्य 'संपत्ति'/विधि जैसी

LinkedListObject<something> current = first; 
While (current != null){ 
yield return current.getValue(); 
current = current.getNext() 
} 

संपादित कोड शामिल होंगे: ध्यान दें कि मैं मुझे किसी भी तृतीय पक्ष एपीआई का उपयोग करने में दिलचस्पी नहीं है। अंतर्निहित जावा कार्यक्षमता केवल।

+0

http का उपयोग किए बिना उपज वापसी का एहसास करने के लिए अपने जावा पुस्तकालय का उपयोग: // stackoverflow.com/questions/1980953/is-there-a-java-equivalent-to-cs-yield-keyword –

+2

मुझे सी # पता नहीं है। उत्सुक, उपज वापसी क्या करती है? – bragboy

+0

इसे जांचें: http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80).aspx –

उत्तर

-21

क्या मुझे यहां कुछ याद आ रही है? पहले से ही java.util.LinkedList है, यह पूरी तरह से जेनेरिक-सक्षम है, और इसमें एक विधि है जो एक इटरेटर लौटाती है।

यदि आप वास्तव में पहिया का पुन: आविष्कार करना चाहते हैं, तो मैं सुझाव दूंगा कि आप लिंक्ड लिस्ट इटरेटर कक्षा बनाने की तलाश में हैं, शायद सूचीकरणकर्ता को लागू करना।यह लिंक की गई सूची में अपनी वर्तमान स्थिति को याद रखेगा और इसे प्रत्येक क्रमिक कॉल पर अग्रिम करेगा।

+2

अपनी खुद की डेटा संरचनाओं के निर्माण के कारण बाद में प्रक्रिया में प्रदर्शन बढ़ाने के लिए व्यापक आवश्यकता के कारण हैं (होश तालिका के रूप में लिंक्ड सूची में उतना ही लागू नहीं हो सकता है)। उप-वर्गीकृत पुनरावर्तक के साथ आपका समाधान यह था कि अंत में मैंने समस्या को हल करने के लिए उपयोग किया। –

+22

मुझे लगता है कि आप कुछ खो रहे हैं (जैसे ओपी है)। सी #/नेट में 'उपज वापसी' नेट केवल एक पुनरावर्तक बनाता है। अगर इटरेटर का उपभोक्ता जल्दी समाप्त हो जाता है, तो लूप जो पुनरावृत्ति उत्पन्न करता है। एक अनंत जनरेटर ऐसा कुछ उदाहरण है जो एक पुनरावर्तक के बिना संभव नहीं है जो संग्रह को मध्यवर्ती चरण के रूप में उपयोग नहीं करता है। उदाहरण के लिए उन्होंने दिया, आप निश्चित रूप से 'लिंक्डलिस्ट' से इटेटरेटर को वापस कर देंगे। –

-1

मैं समझने के लिए उपज करता है की कोशिश की है परंतु सी # अनुभव के बिना मुझे यकीन है कि मेरे पास है, लेकिन मैं वैसे भी कोशिश करेंगे, तो नहीं कर रहा हूँ ...

मैं इसे एक विधि से मूल्यों को लौटने की बात आती है सुझाव है कि निम्नलिखित ...

Something answer = null; 
for (Something author: authors){ 

    if (author.equals("Tom Jones"){ 
    answer = author; 
    break; 
    } 
} 

मैं निम्नलिखित करेंगे ...

public LinkedList<something> getAuthors(LinkedList<something> list){ 
     LinkedList<something> ret = new LinkedList<something>(); 
     for (something s:list){ 
     if (s.equals("abc")) 
      ret.add(s); 
     } 
     return ret; 
    } 

क्या मैंने साजिश खो दी है?

+0

आप कहां लेखकों (लिंक्डलिस्ट) कह रहे हैं? – bragboy

+0

ummm ... आप अपने कोड में कहीं से भी लेखकों को कॉल करेंगे। यदि आप Utils (उदाहरण के रूप में) नामक एक वर्ग बनाते हैं और विधि को स्थिर बनाते हैं तो आप Utils.getAuthors कह सकते हैं (अपनी सूची यहां पास करें); और वह आपकी नई सूची वापस कर देगा। – Paul

+4

मुझे देर हो चुकी है लेकिन आपको समझने की आवश्यकता है कि सी # में, उपज रिटर्न स्टेटमेंट केवल तभी निष्पादित किया जाएगा जब IENumerable के "MoveNext()" विधि को कॉल किया जाता है। आपके उदाहरण के विपरीत IENumerable में आइटम का आलस्य मूल्यांकन किया जाता है। – GuiSim

-1

यदि आप yield return की पूर्ण कार्यक्षमता चाहते हैं, तो आपको शायद इसे दो थ्रेड में सेट करना होगा - एक पहली विधि के लिए, और एक दूसरे के लिए। फिर पहला धागा wait होना चाहिए जब तक कि दूसरा धागा अपना मूल्य कहीं भी सुलभ न हो और notify यह तैयार हो। फिर पहला धागा उस मान को संसाधित करेगा, wait अगले मूल्य के लिए,

+0

मुझे लगता है कि आपने http://en.wikipedia.org/wiki/Coroutine – MartinP

4

मुझे समझ में नहीं आता कि लोग धागे के बारे में क्यों बात कर रहे हैं ... क्या मुझे कुछ उपज रिटर्न के बारे में पता नहीं है?

मेरी समझ के लिए उपज वापसी केवल विधि ढेर को बचाती है और इसे बाद में पुनर्स्थापित करती है। उपज रिटर्न को लागू करने के लिए आपको बस राज्य को मैन्युअल रूप से सहेजना होगा। विवरण के लिए जावा इटरेटर कक्षाएं देखें, हालांकि एक लिंक्ड सूची के लिए आप वर्तमान आइटम को सहेजने से दूर हो सकते हैं। एक सरणी के लिए आपको केवल इंडेक्स की आवश्यकता होगी।

+0

के साथ थ्रेड उलझन में है यह सही है। उपज और उपज रिटर्न सी # में धागे का उपयोग नहीं करते हैं। वे एक संकलन समय परिवर्तन करते हैं और एक राज्य मशीन बनाते हैं, लेकिन वह राज्य मशीन किसी भी अतिरिक्त थ्रेड का उपयोग नहीं करती है (हालांकि यह संभवतः थ्रेड सुरक्षित है)। –

1

पाठकों को छोटे विवरणों को समझने में मदद करने के लिए।

यदि आप सभी परिणामी तत्वों वाली एक नई सूची बनाते हैं और सूची वापस करते हैं, तो यह कोड के लिए पर्याप्त सरल कार्यान्वयन है। आपको आवश्यकतानुसार रोचक डेटा संरचना के रूप में हो सकता है, और सही प्रविष्टियों के लिए स्कैन करते समय, बस सभी मैचों की एक सूची वापस कर दें, और आपका ग्राहक सूची में फिर से चालू होगा।

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

धागे के साथ समाधान एक नई सूची नहीं बनाता है। और यह पहला समाधान जितना सरल है। एकमात्र मुद्दा यह है कि आप एक थ्रेड सिंक्रनाइज़ेशन शामिल करते हैं जो कोड के लिए थोड़ा कठिन है, और इसकी प्रदर्शन दंड है।

तो, हाँ, उपज वापसी महान है और जावा से गायब है। फिर भी कामकाज हैं।

30

आप इटेबल के अज्ञात कार्यान्वयन को वापस कर सकते हैं। प्रभाव बहुत सुंदर हैं, बस यह कि बहुत अधिक verbose है।

public Iterable<String> getStuff() { 
    return new Iterable<String>() { 

     @Override 
     public Iterator<String> iterator() { 
      return new Iterator<String>() { 

       @Override 
       public boolean hasNext() { 
        // TODO code to check next 
       } 

       @Override 
       public String next() { 
        // TODO code to go to next 
       } 

       @Override 
       public void remove() { 
        // TODO code to remove item or throw exception 
       } 

      }; 
     } 
    }; 
} 
13

"उपज वापसी" एक बहुत ही परिष्कृत संकलक चाल है। यह मूल रूप से आपको अपने इटेटरेटर को बनाने के तरीके को "समझने" के किसी भी कष्टप्रद विवरण के बिना आईन्यूमेरेबल को घोषणात्मक रूप से लागू करने देता है। दुर्भाग्यपूर्ण बात यह है कि यह अन्य भाषाओं में अनुवाद नहीं करता है क्योंकि बहुत कम कंपेलरों की क्षमता ऐसी होती है। कुछ तरीकों से "उपज वापसी" क्रांतिकारी के रूप में हानिकारक है।

मूल रूप से सी # में, कंपाइलर IENumerable और IENumerator (टी) के दो कार्यान्वयन उत्पन्न करेगा। यह मूल रूप से आपके "विधि" के स्थानीय चर को साकार करके कार्यान्वित कार्यान्वयन कक्षाओं के उदाहरण के साथ-साथ "उपज रिटर्न" आर्टिफैक्ट युक्त फ़्रेम की जांच के रूप में भी महसूस करता है। एक बार जब आप इसे जानते हैं, तो एक अच्छी तरह से गोल करने वाले डेवलपर के लिए एक ही चीज़ को स्पष्ट रूप से पूरा करना संभव होना चाहिए ... हालांकि संक्षेप में नहीं। प्रदर्शित करने के लिए, मैं कंक्रीट करूँगा!

public static <T> Iterable<T> concat(Iterable<T> x, Iterable<T> y) 
{ 
    for(T e: x) 
    { 
     yield return e; 
    } 

    for(T e: y) 
    { 
     yield return e; 
    } 
} 

// becomes .... 

public static <E> Iterator<E> concat_(Iterable<E> x, Iterator<E> y) 
{ 
    T e1, e2; 
    Iterator<E> i1, i2; 

    Iterator<E> s; 
    Iterator<E> s4 = new Iterator<E>() 
    { 
     public bool hasNext() 
     { 
      return false; 
     } 

     public E next() 
     { 
      throw ... ; 
     } 

     public void remove() 
     { 
      throw ... ; 
     } 
    } 

    Iterator<E> s3 = new Iterator<E>() 
    { 
     Iterator<E> act() 
     { 
      if(i2.hasNext()) 
      { 
       return i2; 
      } 

      i2 = y.iterator(); 
      return (s = s4); 
     } 

     public bool hasNext() 
     { 
      return act().hasNext(); 
     } 

     public E next() 
     { 
      return act().next(); 
     } 

     public void remove() 
     { 
      return i2.remove(); 
     } 
    } 

    Iterator<E> s2 = new Iterator<E>() 
    { 
     Iterator<E> act() 
     { 
      if(i1.hasNext()) 
      { 
       return i1; 
      } 

      i2 = y.iterator(); 
      return (s = s3); 
     } 

     public bool hasNext() 
     { 
      return act().hasNext(); 
     } 

     public E next() 
     { 
      return act().next(); 
     } 

     public void remove() 
     { 
      return i1.remove(); 
     } 
    }; 

    Iterator<E> s1 = new Iterator<E>() 
    { 
     Iterator<E> act() 
     { 
      i1 = x.iterator(); 
      return s = s2; 
     } 

     public bool hasNext() 
     { 
      return act().hasNext(); 
     } 

     public E next() 
     { 
      return act().next(); 
     } 

     public void remove() 
     { 
      return act().remove(); 
     } 
    }; 

    s = s1; 
    return new Iterator<T>() 
    { 
     public bool hasNext() 
     { 
      return s.hasNext(); 
     } 

     public E next() 
     { 
      return s.next(); 
     } 

     public void remove() 
     { 
      return s.remove(); 
     } 
    }; 
} 

public static <T> Iterable<T> concat(Iterable<T> x, Iterable<T> y) 
{ 
    return new Iterable<T>() 
    { 
     public Iterator<T> iterator() 
     { 
      return concat_(x, y) 
     } 
    }; 
} 

// tada! 

आप सभी मेरी 3:00 छद्म जावा क्षमा करेंगे, तो ...

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