2015-05-22 28 views
15

Tôi có một phương thức tạo một đối tượng mỗi khi tôi thực thi nó và tôi cần phải đảo ngược thứ tự mà tôi nhận được chúng. Vì vậy, tôi nghĩ rằng cách tự nhiên để làm điều đó sẽ là một Stack, vì nó là LIFO.Ngăn xếp bằng cách sử dụng API bộ sưu tập trực tuyến Java 8

Tuy nhiên, Java Stack dường như không hoạt động tốt với API phát trực tuyến Java 8 mới.

Nếu tôi làm điều này:

Stack<String> stack = new Stack<String>(); 
    stack.push("A"); 
    stack.push("B"); 
    stack.push("C"); 

    List<String> list = stack.stream().collect(Collectors.toList()); 
    System.out.println("Collected: " + list); 

Kết quả tôi nhận được là:

Collected: [A, B, C] 

Tại sao phải không outputing chúng theo thứ tự LIFO dự kiến ​​vào dòng? Đây có phải là cách đúng để xóa tất cả các mục khỏi ngăn xếp vào danh sách theo thứ tự đúng (LIFO) không?

+0

Tôi hy vọng đó là vì stack kéo dài Vector (trong đó duy trì trật tự chèn gốc; pop mang đến cho bạn ** ** đối tượng cuối cùng trong ngăn xếp). Bạn có nhận được kết quả tương tự bằng cách sử dụng Deque không? ArrayDeque ví dụ đẩy và bật ra phía trước, vì vậy nó sẽ cung cấp cho bạn thứ tự bạn muốn. – azurefrog

+0

'Deque' (và các lớp thực thi của nó) thậm chí không có phương thức' stream() '. Câu hỏi đặt ra là liệu tôi có thể làm việc xung quanh nó không (tôi có thể viết rõ ràng vòng lặp của riêng mình). Lý do tại sao Stack sẽ cung cấp phương thức stream và stream nó theo cách sai, khi người ta mong đợi một lệnh LIFO cho sự lựa chọn của collection được sử dụng. – jbx

+1

Theo [ArrayDeque API] (https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html), nó có cùng phương thức 'stream()' từ java.util .Collection rằng [Stack] (https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html). Tôi không có Java 8 ở đây mặc dù, vì vậy tôi không thể kiểm tra nó. – azurefrog

Trả lời

23

Như đã đề cập trong các nhận xét, chúng tôi đã kiểm tra tốt giao diện Deque cần được ưu tiên hơn.

Nhưng tôi sẽ cho bạn lý do vì sao không nên sử dụng Stack.

Lúc đầu, Tài liệu Java. của Stack nói bản thân:

Một bộ hoàn chỉnh hơn và nhất quán của ngăn xếp hoạt động LIFO là cung cấp bởi giao diện deque và triển khai của nó, mà nên được sử dụng trong ưu tiên cho lớp này. Ví dụ:

Deque stack = new ArrayDeque();

Xem JavaDoc.

Vì vậy, vấn đề với lớp học Stack là gì.

Giống như Martin Fowler đã được đề cập trong cuốn sách của ông Refactoring: Cải thiện thiết kế của Bộ luật hiện tại tại phương pháp refactoring Thay Inheritance với Phái đoàn, một Stack không nên kế thừa từ một Vector.

Một trong những ví dụ điển hình về thừa kế không phù hợp là tạo một lớp con vector. Java 1.1 thực hiện điều này trong các tiện ích của nó (các cậu bé nghịch ngợm!) [6, p. 288]

Thay vào đó, họ nên sử dụng đoàn như trong hình bên dưới, cũng có trong sách.

Xem thêm ở đây: Replace Inheritance with Delegation

Replace Inheritance with Delegation

Vì vậy, nhưng tại sao điều này là một vấn đề:

Bởi vì Stack chỉ có 5 Phương pháp:

  1. pop
  2. đẩy
  3. isEmpty
  4. tìm kiếm
  5. kích thước

    size()isEmpty() được thừa kế từ lớp Vector và các phương pháp khác từ Vector không được sử dụng. Nhưng thông qua kế thừa, các phương thức khác được chuyển tiếp đến lớp Stack mà không có ý nghĩa gì cả.

Và Fowler nói cho vấn đề này:

Bạn có thể sống với tình hình và sử dụng Công ước để nói rằng mặc dù nó là một lớp con, nó chỉ sử dụng một phần của lớp cha chức năng. Nhưng điều đó dẫn đến mã nói một điều khi ý định của bạn là cái gì đó khác — một sự nhầm lẫn bạn nên loại bỏ.

này làm tổn thương Interface Segregation Principle

mà nói:

KHÁCH HÀNG KHÔNG NÊN bị buộc phải phụ thuộc vào giao diện mà họ làm KHÔNG SỬ DỤNG.


Bạn có thể kiểm tra mã nguồn của VectorStack lớp và bạn sẽ thấy rằng các lớp Stack kế thừa spliterator phương pháp và VectorSpliterator innerClass từ lớp Vector.

Phương pháp này được sử dụng bởi giao diện Collection để impl. phiên bản mặc định của phương pháp dòng:

default Stream<E> More ...stream() { 
    return StreamSupport.stream(spliterator(), false); 
} 

Vì vậy, tránh đơn giản là sử dụng lớp VectorStack.

[6] Refactoring: Cải thiện thiết kế của Bộ luật Fowler hiện tại, Martin năm 1997

+1

Cảm ơn bạn đã giải thích chi tiết. – jbx

Các vấn đề liên quan