2016-03-16 31 views
22

Trong Java, người ta có thể dễ dàng tạo ra một luồng vô hạn với Stream.generate(supplier). Tuy nhiên, tôi sẽ cần phải tạo một luồng mà cuối cùng sẽ kết thúc.Tạo luồng hữu hạn trong Java - cách tạo một luồng?

Hãy tưởng tượng, ví dụ, tôi muốn một luồng tất cả các tệp trong một thư mục. Số lượng tệp có thể rất lớn, do đó tôi không thể thu thập tất cả dữ liệu trả trước và tạo luồng từ chúng (thông qua collection.stream()). Tôi cần phải tạo ra các mảnh theo từng mảnh. Nhưng luồng này rõ ràng sẽ kết thúc tại một số điểm và các nhà khai thác thiết bị đầu cuối như (collect() hoặc findAny()) cần phải làm việc trên đó, vì vậy Stream.generate(supplier) không phù hợp ở đây.

Có cách nào dễ dàng hợp lý để thực hiện điều này trong Java, mà không cần triển khai toàn bộ giao diện luồng của riêng tôi không?

Tôi có thể nghĩ về một hack đơn giản - làm điều đó với vô hạn Stream.generate(supplier) và cung cấp không hoặc ném ngoại lệ khi tất cả các giá trị thực được lấy. Nhưng nó sẽ phá vỡ các nhà khai thác dòng tiêu chuẩn, tôi có thể sử dụng nó chỉ với các nhà khai thác của riêng tôi nhận thức được hành vi này.

Làm rõ

dân trong các ý kiến ​​đang đề nghị tôi takeWhile() điều hành. Đây không phải là ý tôi. Làm thế nào để cụm từ câu hỏi tốt hơn ... Tôi không hỏi làm thế nào để lọc (hoặc giới hạn) một luồng hiện có, tôi hỏi làm thế nào để tạo (tạo) luồng - động, mà không tải tất cả các phần tử trả trước, nhưng luồng sẽ có một kích thước hữu hạn (không biết trước).

SOLUTION

Mã tôi đang tìm kiếm là

Iterator it = myCustomIteratorThatGeneratesTheSequence(); 
    StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false); 

Tôi chỉ nhìn vào java.nio.file.Files, làm thế nào các phương pháp list(path) được thực hiện.

+0

Tôi không nghĩ mình hiểu. Bạn đang tìm kiếm một loại 'takeWhile' như ở đây http://stackoverflow.com/q/20746429/1743880? – Tunaki

+1

Bạn đã xem xét các phương pháp như [IntStream.range] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#range-int-int-) và những người bạn? –

+0

'openjdk 9' cung cấp' takeWhile() ' – Andrew

Trả lời

7

Có cách nào dễ dàng hợp lý để thực hiện điều này trong Java, mà không cần triển khai toàn bộ giao diện Truyền trực tiếp không?

Một đơn giản .limit() đảm bảo rằng nó sẽ chấm dứt. Nhưng đó không phải lúc nào cũng đủ mạnh.

Sau Stream phương pháp nhà máy phương pháp đơn giản nhất để tạo nguồn dòng hải quan mà không reimplementing đường ống xử lý dòng được subclassing java.util.Spliterators.AbstractSpliterator<T> và đi qua nó để java.util.stream.StreamSupport.stream(Supplier<? extends Spliterator<T>>, int, boolean)

Nếu bạn đang có ý định sử dụng các luồng song song lưu ý rằng AbstractSpliterator chỉ mang lại tối ưu chia tách. Nếu bạn có quyền kiểm soát nhiều hơn đối với nguồn của mình, việc triển khai hoàn toàn giao diện Spliterator có thể tốt hơn.

Ví dụ: đoạn mã sau sẽ tạo Luồng cung cấp chuỗi vô hạn 1,2,3 ...

trong đó ví dụ cụ thể bạn có thể sử dụng IntStream.range()

Nhưng dòng rõ ràng là sẽ kết thúc tại một số điểm, và khai thác thiết bị đầu cuối như (thu thập() hoặc findAny()) cần phải làm việc trên đó.

hoạt động ngắn mạch như findAny() thực sự có thể kết thúc trên luồng vô hạn, miễn là có bất kỳ phần tử nào phù hợp.

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