2013-06-07 6 views
27

आज मैं java.util.Stack कक्षा में धक्का देने की कोशिश कर रहा था और फिर आइटम्स के माध्यम से Iterator को फिर से (पॉप का उपयोग किए बिना) का उपयोग करने का प्रयास कर रहा था। मैं एलआईएफओ संपत्ति की उम्मीद कर रहा था लेकिन आश्चर्यचकित हुआ।क्या java.util.Stack के इटरेटर में कोई बग है?

यहां वह कोड है जिसे मैं कोशिश कर रहा था।

import java.util.*; 
import java.util.Stack; 

public class Main { 
    public static void main(String[] args) { 
     RobStack<Integer> rstack = new RobStack<Integer>(); // Correct Implementation 
     Stack<Integer> jstack = new Stack<Integer>(); // Default Java Implementation 
     rstack.push(0); jstack.push(0); 
     rstack.push(1); jstack.push(1); 
     rstack.push(2); jstack.push(2); 
     rstack.push(3); jstack.push(3); 

     System.out.print("Algo Stack: "); 
     for (int i : rstack) 
      System.out.print(i + " "); 
     System.out.print("\nJava Stack: "); 
     for (int i : jstack) 
      System.out.print(i + " "); 
    } 

} 

उत्पादन उपरोक्त कार्यक्रम नीचे दिया गया है

Algo Stack: 3 2 1 0 
Java Stack: 0 1 2 3 

ऊपर कोड jstack में डिफ़ॉल्ट जावा कार्यान्वयन का उपयोग करता है और rstack अपने एल्गोरिथ्म वर्ग के लिए implementation provided by Robert Sedgewick उपयोग करता है। मैंने पाया कि प्रो। रॉबर्ट का कार्यान्वयन ठीक काम करता है लेकिन java.util.Stack कार्यान्वयन विफल रहता है।

क्या यह बग है या यह डिज़ाइन है?

+7

नोट: 'Stack' अप्रचलित है, आप का उपयोग करना चाहिए एक' Deque' बजाय (उदाहरण के लिए एक 'ArrayDeque' – fge

+0

और क्या करता है, तो आप दस्तावेज़ में पॉप() आपरेशन – jtomaszk

+2

का उपयोग fge की टिप्पणी के समर्थन में,? [स्टैक] (http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html) वर्ग: 'लिफ़ो स्टैक ऑपरेशंस का एक और पूर्ण और सुसंगत सेट डेक इंटरफेस द्वारा प्रदान किया जाता है और इसके कार्यान्वयन, जिनका उपयोग इस वर्ग के वरीयता में किया जाना चाहिए। – nhahtdh

उत्तर

25

Bug ID 4475301 : RFE: java.util.Stack.iterator() iterates the wrong way देखें। यह व्यवहार (खराब) डिज़ाइन द्वारा है। जावा के अंतर्निहित Stack इटरेटर विधियों को अन्य कक्षाओं से विरासत में मिला है, इसलिए वे आपकी अपेक्षा के अनुसार व्यवहार नहीं करते हैं।

+0

क्यों नहीं जब वे इटरेटर विधि को ओवरराइड करके किया जा सकता है तो वे बग को सही करते हैं? –

+0

@vincentmathew हां, वे प्रोफेसर सेडगेविक के कोड की तरह 'इटेटर()' विधि को ओवरराइड कर सकते थे जिसे आपने लिफ़ो ऑर्डर में पुनरावर्तित करने के लिए लिंक किया था (उसी आंतरिक प्रतिनिधित्व को मानते हुए)। –

+0

@ बिलथीलियार्ड शायद वे नहीं हो सके। "यह एक गलत डिजाइन निर्णय था जिसे स्टैक विस्तार वेक्टर (" है-ए "के बजाय" है-ए ") है। हम सबमिटकर्ता के साथ सहानुभूति रखते हैं लेकिन इसे ठीक नहीं कर सकते क्योंकि संगतता का है।" –

2

सिद्धांत रूप से, आपको Stack से अधिक नहीं होना चाहिए, लेकिन केवल ऊपर से ऊपर या पॉप पर धक्का देना चाहिए। वास्तविक कार्यान्वयन के लिए, जावा सहित अधिकांश भाषाएं Stack को लागू करने के लिए collection type का उपयोग करें। सख्त आवश्यकताओं के दृष्टिकोण से, इसे निरंतर समय push, top and pop ऑपरेशन की अनुमति देनी चाहिए।

कोई अतिरिक्त सुविधाएं (या इस मामले में बग) को केवल अनदेखा किया जाना चाहिए और कोडिंग के लिए भरोसा नहीं किया जाना चाहिए।

1

Eclipse Collections में mutable stack implementation शामिल है जहां इटेटरेटर शीर्ष से नीचे के मान देता है। इस कोड को प्रिंट 3, 2, तो 1.

MutableStack<Integer> stack = ArrayStack.newStack(); 
stack.push(1); 
stack.push(2); 
stack.push(3); 
for (Iterator<Integer> iterator = stack.iterator(); iterator.hasNext();) 
{ 
    Integer each = iterator.next(); 
    System.out.println(each); 
} 

MutableStackMutableCollection या Collection विस्तार नहीं करता है, ताकि आप, ढेर के बीच में से नहीं निकाल सकते, उदाहरण के लिए। forEach(), select(), collect(), anySatisfy(), allSatisfy(), आदि जैसे आंतरिक पुनरावृत्ति पैटर्न को लागू करने वाले तरीके शीर्ष से नीचे के तत्वों को भी संसाधित करते हैं। यह कोड एक ही चीज़ प्रिंट करता है।

stack.forEach(Procedures.println(System.out)); 

नोट: मैं ग्रहण संग्रह के लिए एक committer हूँ।

0

ढेर विरासत .listIterator()AbstractList जो उलटा क्रम यात्रा की अनुमति देता है से।

Stack<Integer> stack = new Stack<Integer>(); 
stack.push(1); 
stack.push(2); 
stack.push(3); 
for (ListIterator<Integer> iterator = stack.listIterator(stack.size()); iterator.hasPrevious();) { 
    Integer integer = iterator.previous(); 
    System.out.println(integer); 
} 
// Output: 3 2 1 
9

आपको स्टैक के बजाय डेक का उपयोग करना चाहिए।

Deque<Integer> stack = new ArrayDeque<Integer>(); 

See Oracle Doc

2

शायद, आप ऊपर से नीचे तक ढेर के भीतर आइटम मुद्रित करने के लिए .Get उपयोग कर सकते हैं()।

Stack<Integer> stack = new Stack<Integer>(); 
stack.push(3); 
stack.push(2); 
stack.push(1); 
// print from top to bottom 
for(int i = stack.size() - 1; i >= 0; i--){ 
    System.out.println(stack.get(i)); 
} 
/* 
output 
1 
2 
3 
*/ 
संबंधित मुद्दे