2016-08-13 8 views
6

मैं एक इटरेटर क्लास बनाना चाहता हूं जो मुझे जेनेरिक प्रकारों (जैसे lst1 पूर्णांक, lst2 स्ट्रिंग) के साथ एक आइटम के बाद सूचियों के माध्यम से पुन: सक्रिय करने की अनुमति देता है। इसके लिए मुझे निम्नलिखित दी गई स्थिति पर विचार करना होगा।जावा में किसी अन्य के बाद विभिन्न प्रकार के एक आइटम के साथ दो जेनेरिक सूचियों के माध्यम से कैसे पुनरावृत्ति करें?

इंटरफ़ेस एक सामान्य इटरेटर है। कोड का यह हिस्सा संशोधित नहीं किया जा सकता है।

interface Iterator<E> { 
E next(); 
boolean hasNext(); 
} 

सूची वर्ग को निम्नानुसार परिभाषित किया गया है। सबसे महत्वपूर्ण, एक सूची वस्तु विधि इटरेटर() के साथ एक इटेरेटर ऑब्जेक्ट वापस कर सकती है। कोड का यह हिस्सा संशोधित नहीं किया जा सकता है।

class List<T> { 
class ListNode { 
    T val; 
    ListNode next; 

    ListNode (T v) { 
     val = v; next = null; 
    } 
} 

ListNode head; 

List (ListNode hd) { head = hd; } 
List() { this(null); } 

void prepend (T val) { 
    ListNode p = new ListNode(val); 
    p.next = head; 
    head = p; 
} 

//some other methods 

class ListIterator implements Iterator<T> { 
    ListNode pos; 

    ListIterator() { 
     pos = head; 
    } 

    public T next() {  
     T res = pos.val; 
     pos = pos.next; 
     return res; 
    } 

    public boolean hasNext() { 
     return pos != null; 
    } 
} 

Iterator<T> getIterator() {   
    return this.new ListIterator(); 
} 
} 

मान लें कि दोनों सूची में एक ही प्रकार है और अब उनके पास भी वही लंबाई है। मैंने दो इटरेटर ऑब्जेक्ट्स के साथ एक क्लास बनाने की कोशिश की और इंटरफ़ेस इटरेटर को लागू करने के लिए इटरेटर ऑब्जेक्ट्स के तरीकों का उपयोग किया। कोड का यह हिस्सा मेरे द्वारा बनाया गया है और संशोधित किया जा सकता है।

class ZipIterator<T> implements Iterator<T> 
{ 
int counter; 
Iterator<T> first; 
Iterator<T> second; 

ZipIterator (Iterator<T> f, Iterator<T> s) 
{ 
    first = f; 
    second = s; 
    counter = 0; 
} 

public T next() 
{ 
    if (counter % 2 == 0) 
    { 
     counter++; 
     return first.next(); 
    } 

    else 
    { 
     counter++; 
     return second.next(); 
    } 

} 
public boolean hasNext() 
{ 
    if (counter % 2 == 0) 
     return first.hasNext(); 
    else 
     return second.hasNext(); 
} 
} 

यह एक ही प्रकार के साथ दो सूची के लिए ठीक काम करता है। यहाँ कोड और आउटपुट मैं परीक्षण के लिए इस्तेमाल किया है:

class IteratorUtils 
{ 
public static void main (String[] args) 
{ 
    List<Integer> lst1 = new List<>(); 
    List<Integer> lst2 = new List<>(); 
    lst1.prepend(3); 
    lst1.prepend(2); 
    lst1.prepend(1); 
    lst2.prepend(8); 
    lst2.prepend(9); 
    lst2.prepend(10); 
    Iterator<Integer> it1 = lst1.getIterator(); 
    Iterator<Integer> it2 = lst2.getIterator(); 
    ZipIterator<Integer> zit = new ZipIterator<>(it1, it2); 
    while (zit.hasNext()) 
    { 
     System.out.println(zit.next()); 
    } 
} 
} 

आउटपुट:

1 
10 
2 
9 
3 
8 

अब मैं एक सामान्य तरीके ZipIterator लागू करना चाहते हैं, तो मैं विभिन्न प्रकार के साथ दो सूचियों का उपयोग कर सकते हैं वस्तुओं (जैसे पूर्णांक और स्ट्रिंग)। मुझे पता है कि मुझे कक्षा ZipIterator को बदलना है, इसलिए अगला तरीका() एक सामान्य प्रकार देता है लेकिन मुझे नहीं पता कि कैसे। यह एक विश्वविद्यालय कार्य है जो मुझे करना है और प्रोफेसर ने संकेत दिया है "जंगली कार्ड्स का उपयोग करें जैसे: टी, सुपर टी, विस्तारित करता है" ऑब्जेक्ट बढ़ाता है। लेकिन जंगली कार्ड के साथ मैं केवल विरासत दिशा में या उसके खिलाफ प्रकार निर्दिष्ट कर सकता हूं, है ना? क्या ज़िप्टरेटर वर्ग को इस तरह से बदलना संभव है जिससे यह दो प्रकार के ऑब्जेक्टर्स को विभिन्न प्रकारों से स्वीकार कर सके?

+0

वहाँ पर किसी भी बाधाओं हैं दो प्रकार? यदि नहीं, तो आप सबसे अच्छा कर सकते हैं 'ऑब्जेक्ट' वापस कर सकते हैं। –

+0

आपके द्वारा पोस्ट किए गए कोड का कौन सा हिस्सा असाइनमेंट में दिया गया है और आप किस भाग को संशोधित कर सकते हैं? – user1803551

+0

ठीक है, मैं जवाब दे सकता हूं, लेकिन यह असाइनमेंट की सभी कठिनाई को दूर करेगा। हालांकि मैं एक संकेत दे सकता हूं, [पीईसीएस] पर एक नज़र डालें (http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super)। –

उत्तर

3

मैं पूर्ण समाधान दे देंगे नहीं है (और आपके प्रयास आप इसे नहीं करना चाहती द्वारा पहचानने), लेकिन मैं एक तरह से आप इसे अपने आप को खोजने के दूँगी कि में समझाने का प्रयास करेंगे।

सब एक असंबंधित नोट के पहले: आप एक विशिष्ट यात्रा के क्रम निर्दिष्ट कर रहे हैं। मुझे लगता है कि यह ठीक है और मैं इसे छूंगा नहीं।

आपका प्रोफेसर आप घिरा जेनरिक का उपयोग करने का संकेत दिया था। आइए समझें कि उन्हें क्यों जरूरी है (tutorial here और/या here देखें)। यदि आपको एक ऐसी विधि लिखने के लिए कहा गया था जो 2 अज्ञात प्रकारों में से किसी एक का तर्क लेता है, तो आपका समाधान उनके सामान्य सुपरक्लास - Object को ढूंढना और लेना होगा।

जेनरिक में स्थिति समान है - आम विभाजक मिल जाए, केवल वाक्य रचना में थोड़ा और अधिक मुश्किल है। आप निर्माता

ZipIterator(Iterator<Object> f, Iterator<Object> s) {...} 

List<Integer> lst1 = new List<>(); 
List<String> lst2 = new List<>(); 
new ZipIterator(it1, it2); 

लिखने और आरंभीकरण प्रयास करने के लिए थे, तो आप एक संकलन त्रुटि मिलेगा (यह पढ़ें)। क्योंकि एक List<String> एक List<Object> नहीं है, भले ही एक String एक Object होती है।यह करने के लिए सही तरीका

ZipIterator(Iterator<? extends Object> f, Iterator<? extends Object> s) {...} 

जहां ? extends Object का अर्थ है "किसी भी प्रकार कि Object फैली" (जो उन सभी को है क्योंकि Object है ...) है।

तो आपके पास कन्स्ट्रक्टर है, और इसे समायोजित करने के लिए आपको अपनी कक्षा में बदलाव करने की आवश्यकता होगी। आपको दिए गए Iterator<E> को लागू करने की भी आवश्यकता नहीं है, आप बस उन लोगों में से 2 को पकड़ लें जिन्हें आप पहले से ही करते हैं। अंत में, कक्षा के लिए सामान्य प्रकार की आवश्यकता नहीं होती है: क्योंकि इसकी next विधि किसी भी प्रकार को वापस करने में सक्षम होना चाहिए, यह हमेशा Object देता है।

यदि इस समस्या पर आपके भविष्य के प्रयासों के दौरान आपके कोई प्रश्न हैं, या आप पाते हैं कि यह समाधान असाइनमेंट की आवश्यकताओं के अनुरूप नहीं है, तो टिप्पणी पोस्ट करने के लिए स्वतंत्र महसूस करें।

0

मुझे पता है कि मुझे कक्षा ZipIterator को बदलना है, इसलिए अगला तरीका() एक सामान्य प्रकार देता है लेकिन मुझे नहीं पता कि कैसे।

यह बिल्कुल सही नहीं है। चूंकि ZipIterator<T>Iterator<T> बढ़ाता है, यह वास्तव में पत्थर में स्थापित है कि इसकी next() विधि T वापस करनी होगी। और यह समझ में आता है: इटरेटर के प्रकार पैरामीटर का पूरा बिंदु आपको इस प्रकार को निर्दिष्ट करने देता है कि इसकी next() विधि वापस आ जाएगी।

इसके बजाय, आपके सभी प्रोफेसर चाहता है कि ZipIterator<...> को विभिन्न प्रकार के तर्कों के साथ दो पुनरावृत्तियों से ZipIterator<...> बनाएं। उदाहरण के लिए, (रों) वह लिखने में सक्षम होना चाहता है:

List<Integer> listOfIntegers = ...; 
List<String> listOfStrings = ...; 

ZipIterator<Object> zipIterator = 
    new ZipIterator<>(listOfIntegers.getIterator(), listOfStrings.getIterator()); 

ध्यान दें कि, zipIterator.next() के बाद से कभी कभी एक Integer और कभी कभी एक String वापस आ जाएगी, हम ZipIterator<Object> की तरह कुछ है कि दोनों संभावनाओं के लिए अनुमति देता है के साथ जाना पड़ा। अन्य विकल्पों में ZipIterator<Serializable> या ZipIterator<Comparable<?>> शामिल हैं, Integer -s और String -s Serializable और Comparable<?> दोनों हैं।


तो समस्या यह है कि अपने प्रोफेसर को हल करना चाहता है कि अपने वर्तमान कोड में, अपने निर्माता दोनों iterators की आवश्यकता है ठीक उसी प्रकार तर्क के लिए (एक दूसरे के रूप में, और ZipIterator खुद के रूप में) है:

ZipIterator (Iterator<T> f, Iterator<T> s) 

क्या आप इसे ठीक करने के तरीके देखते हैं?

+0

प्रश्न पर टिप्पणियां पढ़ें। आपकी प्रारंभिक धारणा इतनी सटीक नहीं है। – user1803551

+0

@ user1803551: मैंने टिप्पणियां पढ़ीं, और मैं अपनी "धारणा" से खड़ा हूं। डिजाइन के लिए 'इटरेटर ' लागू करना आवश्यक है, और हमें इसे फेंकना नहीं चाहिए क्योंकि प्रोफेसर ने इसे लिखने के लिए छात्र को छोड़ दिया था। हो सकता है कि छात्र उस बिट को छोड़कर और असाइनमेंट पर आंशिक क्रेडिट लेकर "आसान तरीका" ढूंढ सकें, लेकिन आप इसे क्यों प्रोत्साहित करेंगे? – ruakh

+0

यदि यह डिज़ाइन है तो यह "पत्थर में सेट नहीं" है - यह एक विकल्प है। मुझे नहीं लगता कि आप क्यों मानते हैं कि इसे लागू नहीं करने के परिणामस्वरूप आंशिक क्रेडिट होगा। हमारे पास ग्रेडिंग विधि और न ही किसी विशिष्ट आवश्यकताओं पर कोई जानकारी नहीं है। मैं यह भी नहीं देखता कि क्यों इसे छोड़ना एक "आसान तरीका" है, यदि आवश्यक नहीं है तो इसे छोड़ना सही विकल्प है। यदि कुछ भी हो, तो प्रोफेसर समाधान में वाइल्डकार्ड का उपयोग करने पर संकेत देता है। – user1803551

0

जैसा कि मैं समझता हूं कि आप समाधान के विभिन्न प्रकारों की सूची में पुन: प्रयास करना चाहते हैं, यह है कि आपके कन्स्ट्रक्टर को स्वीकार करने के लिए इटेटरेटर आवश्यकता को पूरा करता है कि यह ऑब्जेक्ट को विस्तारित करने वाली किसी चीज का पुनरावर्तक है लेकिन इससे पुनर्प्राप्त वस्तुओं के आपके उपयोग को सीमित कर दिया जाएगा बस इसे ऑब्जेक्ट्स के रूप में उपयोग करें या आपको आगे के कार्यों को प्राप्त करने के लिए उन्हें कम करना होगा, कन्स्ट्रक्टर को स्वीकार करने के लिए कम प्रतिबंधक दृष्टिकोण यह है कि यह किसी भी चीज का पुनरावर्तक है जो इस ZipIterator(Iterator<? extends T> f, Iterator<? extends T> s) जैसे निकटतम सामान्य पूर्वजों को विस्तारित करता है, इसलिए आपकी कक्षा इस

class ZipIterator<T> implements Iterator<T> { 

    int counter; 
    Iterator<? extends T> first; 
    Iterator<? extends T> second; 

    ZipIterator(Iterator<? extends T> f, Iterator<? extends T> s) { 
     first = f; 
     second = s; 
     counter = 0; 
    } 

    @Override 
    public T next() { 
     if (counter % 2 == 0) { 
      counter++; 
      return first.next(); 
     } else { 
      counter++; 
      return second.next(); 
     } 
    } 

    @Override 
    public boolean hasNext() { 
     if (counter % 2 == 0) { 
      return first.hasNext(); 
     } else { 
      return second.hasNext(); 
     } 
    } 

} 

फिर इसका उपयोग करने के लिए आप सबसे उपयुक्त सुपर क्लास निर्दिष्ट कर सकते हैं कि दोनों प्रकार टी को अभिसरण करते हैं ओ यह है, यह है के मामलों में Object आप ZipIterator<Object> zit = लिख सकते हैं, निम्नलिखित कोड आप एक मनमाना उपयोग के मामले

 List<StringBuilder> bl= Arrays.asList(new StringBuilder("hi i'm builder")); 
     List<String> sl = Arrays.asList("hi i'm string"); 
     ZipIterator<CharSequence> zit = new ZipIterator<>(bl.iterator(), sl.iterator()); 
     while (zit.hasNext()) { 
      CharSequence cs = zit.next(); 
      System.out.println(cs.subSequence(6,cs.length())); 
     } 
0

मदद के लिए धन्यवाद दिखाई देगा। मैंने बहुत कुछ सीखा है। यहां मेरा समाधान और कार्य के लिए कुछ और स्पष्टीकरण आता है।

कृपया पहले ध्यान दें, कि ज़िप्टरेटर वर्ग का डिज़ाइन पत्थर में सेट नहीं है। ZipIterator मेरे द्वारा डिजाइन किया गया था। एक और समाधान हो सकता है लेकिन यह मेरा प्रयास था।

कार्य निर्दिष्ट करने के लिए: "कृपया कई तरीके के साथ एक कक्षा IteratorUtils निर्माण विधि जिप दो इटरेटर वस्तुओं प्राप्त करता है और एक इटरेटर वस्तु है, जो दो प्राप्त इटरेटर वस्तुओं के आइटम के माध्यम से बारी दोहराता द्वारा दिया iterator देता है।। ज़िप फ़ंक्शन को छोटे इटरेटर ऑब्जेक्ट के अंतिम आइटम के बाद रोकना चाहिए। वाइल्डकार्ड का उपयोग करें ताकि आप ज़िप फ़ंक्शन को इटरेटर ऑब्जेक्ट्स के विभिन्न प्रकारों पर लागू कर सकें। "

इसके लिए मैंने पहले श्रेणी IteratorUtils बनाया था। कृपया ध्यान दें कि ज़िप फ़ंक्शन का डिज़ाइन पत्थर में भी सेट नहीं है। कार्य में यह केवल इतना कहता है: "विधि ज़िप को दो इटरेटर ऑब्जेक्ट प्राप्त होते हैं और एक इटेटरेटर ऑब्जेक्ट देता है, जो दो इटेटरेटर ऑब्जेक्ट्स के आइटमों के माध्यम से वैकल्पिक होता है।"

class IteratorUtils 
{ 
static ZipIterator zip (Iterator<? extends Object> first, Iterator<? extends Object> second) 
{ 
    return new ZipIterator(first, second); 
} 
} 

फिर मैंने कक्षा ZipIterator बनाया। आपके उत्तरों और कुछ ट्यूटोरियल पढ़ने के बाद मैंने इस कार्य में बाध्य प्रकार पैरामीटर का अर्थ समझा। उपयोगकर्ता 1803551 की तरह, ज़िप्टरेटर वर्ग सामान्य नहीं होना चाहिए। मुझे बस यह महसूस करना पड़ा कि मैं आम सुपरक्लास (ऑब्जेक्ट) ढूंढने के लिए टोपी हूं। तो मैं निम्नलिखित करने के लिए अपने ZipIterator वर्ग बदलना पड़ा: अपने मुख्य विधि में

class ZipIterator 
{ 
int counter; 
Iterator first; 
Iterator second; 

ZipIterator (Iterator<? extends Object> f, Iterator<? extends Object> s) 
{ 
    first = f; 
    second = s; 
    counter = 0; 
} 

public Object next() 
{ 
    if (counter % 2 == 0) 
    { 
     counter++; 
     return first.next(); 
    } 

    else 
    { 
     counter++; 
     return second.next(); 
    } 

} 

public boolean hasNext() 
{ 
    if (counter % 2 == 0) 
     return first.hasNext(); 
    else 
     return second.hasNext(); 
} 
} 

मैं निम्नलिखित कोड का उपयोग करें:

public static void main (String[] args) 
{ 
    List<Integer> lst1 = new List<>(); 
    List<String> lst2 = new List<>(); 
    lst1.prepend(3); 
    lst1.prepend(2); 
    lst1.prepend(1); 
    lst2.prepend("three"); 
    lst2.prepend("two"); 
    lst2.prepend("one"); 
    Iterator<Integer> it1 = lst1.getIterator(); 
    Iterator<String> it2 = lst2.getIterator(); 
    ZipIterator zit = zip(it1, it2); 
    while (zit.hasNext()) 
    { 
     System.out.println(zit.next()); 
    } 
} 

आउटपुट:

1 
one 
2 
two 
3 
three 
+0

अच्छा! आपके समाधान के बारे में एक बात: 'Iterator' फ़ील्ड को कच्चे प्रकार के रूप में न छोड़ें - उन्हें सामान्य भी बनाएं। आपके प्रश्न के बारे में एक बात: आपने यहां अपने उत्तर में स्पष्ट नियम जोड़े हैं, लेकिन यदि आप भ्रम से बचने के लिए उन्हें प्रश्न में जोड़ना चाहते हैं तो इससे मदद मिलेगी। सर्वोत्तम अभ्यास असाइनमेंट को बिल्कुल उद्धृत करना है। – user1803551

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

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