2013-06-07 29 views
27

Hôm nay tôi đã cố gắng để đẩy trong java.util.Stack lớp và sau đó sử dụng Iterator để lặp (không sử dụng pop) thông qua các mục. Tôi đã mong đợi tài sản LIFO nhưng đã ngạc nhiên.Có lỗi trong Iterator của java.util.Stack không?

Đây là mã mà tôi đang thử.

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 + " "); 
    } 

} 

Kết quả chương trình trên được đưa ra dưới đây:

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

Trong đoạn mã trên jstack sử dụng thực hiện Java mặc định và rstack sử dụng implementation provided by Robert Sedgewick cho lớp thuật toán của mình. Tôi thấy rằng việc thực hiện của Giáo sư Robert hoạt động tốt nhưng việc triển khai java.util.Stack không thành công.

Đây có phải là lỗi hoặc là nó bằng thiết kế?

+7

Lưu ý: 'Stack' là lỗi thời, bạn nên sử dụng một 'Deque' thay (ví dụ một' ArrayDeque' – fge

+0

Và những gì nếu bạn sử dụng pop() hoạt động – jtomaszk

+2

Để hỗ trợ bình luận FGE, trong doc? của lớp [Stack] (http://docs.oracle.com/javase/7/docs/api/java/util/Stack.html): 'Một bộ hoàn chỉnh hơn và nhất quán của các hoạt động ngăn xếp LIFO được cung cấp bởi giao diện Deque và các triển khai của nó, nên được sử dụng ưu tiên cho lớp này.' – nhahtdh

Trả lời

25

Xem Bug ID 4475301 : RFE: java.util.Stack.iterator() iterates the wrong way. Hành vi này là do thiết kế (xấu). Các phương thức iterator Stack được xây dựng sẵn của Java được kế thừa từ các lớp khác, vì vậy chúng không hoạt động như bạn mong đợi.

+0

Tại sao không họ sửa lỗi khi nó có thể được thực hiện bằng cách chỉ ghi đè phương pháp Iterator? –

+0

@vincentmathew Có, họ có thể đã ghi đè phương thức 'iterator()' giống như trong đoạn mã của Giáo sư Sedgewick mà bạn đã liên kết để làm cho nó lặp lại theo thứ tự LIFO (giả sử cùng một biểu diễn bên trong). –

+0

@BilltheLiazard Có lẽ họ không thể có. "Đó là một quyết định thiết kế không chính xác để có Stack mở rộng Vector (" is-a "thay vì" has-a "). Chúng tôi thông cảm với người gửi nhưng không thể khắc phục điều này vì khả năng tương thích." –

2

Cũng theo nguyên tắc, bạn không nên lặp qua một số Stack mà chỉ đẩy lên trên hoặc bật từ trên cùng. Đối với việc triển khai thực tế, hầu hết các ngôn ngữ, kể cả Java, hãy sử dụng một số khác collection type để triển khai Stack. Từ quan điểm yêu cầu nghiêm ngặt, nó nên cho phép hoạt động liên tục push, top and pop.

Bất kỳ tính năng bổ sung nào (hoặc lỗi trong trường hợp này), chỉ nên bỏ qua và không dựa vào mã hóa.

1

Eclipse Collections bao gồm mutable stack implementation trong đó trình vòng lặp trả về giá trị từ trên xuống dưới. Mã này in 3, 2, sau đó 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); 
} 

MutableStack không mở rộng MutableCollection hay Collection, do đó bạn không thể loại bỏ từ giữa ngăn xếp, ví dụ. Các phương pháp triển khai các mẫu lặp nội bộ như forEach(), select(), collect(), anySatisfy(), allSatisfy(), v.v ... cũng xử lý các phần tử từ trên xuống dưới. Mã này in cùng một thứ.

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

Lưu ý: Tôi là người bắt đầu bộ sưu tập Eclipse.

0

Chồng kế thừa .listIterator() từ AbstractList cho phép lặp lại thứ tự ngược.

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

Bạn nên sử dụng Deque thay vì Stack.

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

See Oracle Doc

2

Có lẽ, bạn có thể sử dụng .get() để in các mục trong ngăn xếp từ trên xuống dưới.

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 
*/ 
Các vấn đề liên quan