2012-11-20 13 views
15

मेरे पास एक लिंक्डलिस्ट है जिस पर मुझे कई बार पीछे और पीछे की आवश्यकता है। मैं वर्कफ़्लो में पृष्ठों की एक श्रृंखला का ट्रैक रखने के लिए इसका उपयोग कर रहा हूं जो गतिशील रूप से बनाया जाएगा। जैसा कि मैं उम्मीद करता हूं यह व्यवहार नहीं करता है।जावा में एक लिंक्डलिस्ट पर आगे और आगे जाने के लिए ListIterator का उपयोग

LinkedList<String> navigationCases; 
navigationCases.add("page1"); 
navigationCases.add("page2"); 
navigationCases.add("page3"); 
navigationCases.add("page4"); 

ListIterator navigationItr = navigationCases.listIterator(); 
navigationItr.next(); // Returns page1 
navigationItr.next(); // Returns page2 
navigationItr.previous(); //Returns page2 again 
navigationItr.next(); //Returns page2 again 

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

एक ListIterator कोई मौजूदा है तत्व; इसकी कर्सर स्थिति हमेशा उस तत्व के बीच होती है जो पिछले() और उस कॉल को वापस कॉल द्वारा वापस कर दी जाएगी जिसे कॉल द्वारा अगले() पर वापस किया जाएगा।

और:

(अगला) सूची में अगले तत्व देता है। इस विधि को सूची के माध्यम से पुनरावृत्त करने के लिए बार-बार कहा जा सकता है, या आगे और आगे जाने के लिए कॉल के साथ इंटरमीक्स किया जा सकता है। (ध्यान दें कि अगली और पिछली बार कॉल करने के लिए कॉल बार-बार वही तत्व लौटाएंगे।)

तो इसे पढ़ने के बाद, यह स्पष्ट है कि मेरा कोड इस तरह से व्यवहार क्यों कर रहा है। मुझे समझ में नहीं आता कि इसे इस तरह क्यों काम करना चाहिए। यहां तक ​​कि इस कार्यान्वयन को समायोजित करने के लिए पीछे की तरफ झुकना प्रतीत होता है:

ध्यान दें कि कर्सर स्थिति के संदर्भ में निकालें() और सेट (ऑब्जेक्ट) विधियों को परिभाषित नहीं किया गया है; उन्हें अगली() या पिछले() पर कॉल द्वारा लौटाए गए अंतिम तत्व पर काम करने के लिए परिभाषित किया जाता है।

संकल्पनात्मक रूप से, एक लिंक्डलिस्ट मेरे वर्कफ़्लो मामलों को बहुत अच्छी तरह से मॉडल करने लगती थी, लेकिन मैं इस तरह से व्यवहार करने वाले इटरेटर का उपयोग नहीं कर सकता। क्या मुझे यहां कुछ याद आ रही है, या क्या मुझे अपनी खुद की कक्षा को मामलों की सूची बनाए रखना चाहिए और उनसे नेविगेट करना चाहिए?

+1

आप "इस तरह से व्यवहार करने वाले एक इटरेटर का उपयोग क्यों नहीं कर सकते"? बाकी दुनिया करता है। बस स्वीकार करें कि यह कैसे काम करता है और इसका लाभ उठाने के लिए इसका उपयोग किया जाता है। – Madbreaks

+2

यह इस तरह से व्यवहार करता है क्योंकि यह अंत कार्य से शुरू होने से शुरू होता है और शुरुआत से ही शुरू होता है। –

+0

@ मैडब्रेक्स इस उपयोग के मामले को "उपयोग करने के इरादे" से अलग कैसे किया जाता है? अगले के लिए पूछने के तुरंत बाद पिछले तत्व के बारे में पूछने के "विशेष" मामले के लिए मैं कैसे खाता करूं? या पिछले के लिए पूछने के तुरंत बाद पूछना? – user1535568

उत्तर

9

यह आपके काम करना चाहिए:

public class Main { 
    public static void main(String[] args) { 
     final LinkedList<String> list = new LinkedList<String>(); 

     list.add ("1"); list.add ("2"); list.add ("3"); list.add ("4"); 

     final MyIterator<String> it = new MyIterator (list.listIterator()); 

     System.out.println(it.next()); 
     System.out.println(it.next()); 
     System.out.println(it.next()); 
     System.out.println(it.previous()); 
     System.out.println(it.previous()); 
     System.out.println(it.next()); 
    } 

    public static class MyIterator<T> { 

     private final ListIterator<T> listIterator; 

     private boolean nextWasCalled = false; 
     private boolean previousWasCalled = false; 

     public MyIterator(ListIterator<T> listIterator) { 
      this.listIterator = listIterator; 
     } 

     public T next() { 
      nextWasCalled = true; 
      if (previousWasCalled) { 
       previousWasCalled = false; 
       listIterator.next(); 
      } 
      return listIterator.next(); 
     } 

     public T previous() { 
      if (nextWasCalled) { 
       listIterator.previous(); 
       nextWasCalled = false; 
      } 
      previousWasCalled = true; 
      return listIterator.previous(); 
     } 

    } 
} 

और एक fiddle इसके लिए ।

+0

हां, मुझे पिछले ऑपरेशन को याद रखने के आसपास कोई रास्ता नहीं दिख रहा है। धन्यवाद! – user1535568

-1
इस (स्यूडोकोड) की तरह

क्या कुछ -

class SkipIterator extends ListIterator { 

    public E previous(){ 
     E n = super.previous(); 
     return super.previous(); 
    } 

    ... 

} 
तो

:

LinkedList<String> navigationCases; 
navigationCases.add("page1"); 
navigationCases.add("page2"); 
navigationCases.add("page3"); 
navigationCases.add("page4"); 

SkipIterator navigationItr = (SkipIterator)navigationCases.listIterator(); 
navigationItr.next(); // Returns page1 
navigationItr.next(); // Returns page2 
navigationItr.previous(); // Returns page1 

चीयर्स

+1

दुर्भाग्यवश, मैं केवल पिछला ऑपरेशन था()। अगर अगली बार कॉल नहीं किया गया था, तो पिछले() को दो बार कॉल करने से वास्तव में इटेटरेटर सूची में एक तत्व छोड़ने का कारण बन जाएगा। – user1535568

+0

ठीक है, तो उस तर्क को बनाएं। :) विचार यह है कि आप बेस क्लास का विस्तार कर सकते हैं और आपके उपयोग के मामले में आवश्यक तर्क शामिल कर सकते हैं। – Madbreaks

+0

हाँ आप सही हैं। धन्यवाद! – user1535568

0

ListIterator इस तरह से व्यवहार करने के लिए डिज़ाइन किया गया था। तर्क के लिए श्याज के जवाब के नीचे वार्तालाप देखें।

मुझे यह व्यवहार बेवकूफ से परे होने लगता है, और इसके बजाय एक बहुत ही सरल विकल्प लिखा है। यहाँ ArrayLists के लिए एक विस्तार समारोह के साथ Kotlin कोड है:

class ListIterator<E>(var list: ArrayList<E>) : Iterator<E> { 

    private var cursor: Int = 0 

    fun replace(newList: ArrayList<E>) { 
     list = newList 
     cursor = 0 
    } 

    override fun hasNext(): Boolean { 
     return cursor + 1 < list.size 
    } 

    override fun next(): E { 
     cursor++ 
     return current() 
    } 

    fun hasPrevious(): Boolean { 
     return 0 <= cursor - 1 
    } 

    fun previous(): E { 
     cursor-- 
     return current() 
    } 

    fun current(): E { 
     return list[cursor] 
    } 

} 

fun <E> ArrayList<E>.listFlippingIterator() = ListIterator(this) 

आप हटाने कार्यक्षमता शामिल करना चाहते हैं, मैं अत्यधिक एपीआई लिख स्पष्ट इटरेटर निर्देश देने के लिए अगर यह बाईं या दाईं ओर, उदा निकाल देना चाहिए की सिफारिश उन विधियों को removeNext() और removePrevious() के रूप में परिभाषित करके।

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