Tôi đã làm một cuộc điều tra trong một số danh sách gửi thư lambda của dự án và tôi nghĩ rằng tôi đã tìm thấy một vài cuộc thảo luận thú vị.
Tôi đã không tìm thấy một lời giải thích thỏa đáng cho đến nay. Sau khi đọc tất cả những điều này tôi đã kết luận đó chỉ là một thiếu sót. Nhưng bạn có thể thấy ở đây rằng nó đã được thảo luận nhiều lần trong nhiều năm trong quá trình thiết kế API.
Chuyên gia kỹ thuật Lambda Libs
Tôi tìm thấy một cuộc thảo luận về điều này trong danh sách gửi thư của Chuyên gia Lambda Libs :
Trong Iterable / Iterator.stream () Sam Pullara đã nói:
Tôi đã làm việc với Brian để xem cách giới hạn chức năng / giới hạn [1] có thể được thực hiện và anh ấy đề nghị chuyển đổi sang Iterator là cách phù hợp để thực hiện. Tôi đã nghĩ về giải pháp đó nhưng không tìm thấy bất kỳ cách rõ ràng nào để lấy một trình vòng lặp và biến nó thành một luồng. Hóa ra nó ở trong đó, trước tiên bạn chỉ cần chuyển đổi iterator thành một spliterator và sau đó chuyển đổi spliterator thành một luồng. Vì vậy, điều này mang lại cho tôi để xem xét lại liệu chúng ta nên có những cái này treo trực tiếp một trong số Iterable / Iterator hoặc cả hai.
Đề nghị của tôi là ít nhất có nó trên Iterator để bạn có thể di chuyển sạch sẽ giữa hai thế giới và nó cũng có thể dễ dàng khám phá hơn là phải làm:
Streams.stream (Spliterators.spliteratorUn UnknownSize (iterator, Spliterator.ORDERED))
Và sau đó Brian Goetz trả lời :
Tôi nghĩ rằng quan điểm của Sam là có rất nhiều lớp thư viện cung cấp cho bạn một Iterator nhưng đừng để bạn nhất thiết phải viết bộ chia của riêng bạn. Vì vậy, tất cả những gì bạn có thể làm là gọi luồng (spliteratorUn UnknownSize (iterator)). Sam đang đề nghị chúng tôi xác định Iterator.stream () để làm điều đó cho bạn.
Tôi muốn giữ các phương thức stream () và spliterator () như dành cho người viết thư viện / người dùng nâng cao.
Và sau đó
"Cho rằng việc viết Spliterator dễ hơn viết Iterator, tôi thích chỉ viết Spliterator thay vì Iterator (Iterator là 90s :)"
Bạn đang thiếu điểm, mặc dù. Có hàng trăm lớp học ngoài đó đã trao cho bạn một Iterator. Và nhiều trong số chúng không sẵn sàng.
Thảo luận trước đây trong danh sách gửi thư Lambda
Đây có thể không phải là câu trả lời bạn đang tìm kiếm nhưng trong danh sách gửi thư của Dự án Lambda, điều này đã được thảo luận ngắn gọn. Có lẽ điều này giúp thúc đẩy một cuộc thảo luận rộng hơn về chủ đề này.
Theo lời của Brian Goetz trong Luồng từ Iterable :
Lùi lại...
Có rất nhiều cách để tạo Stream. Bạn càng có nhiều thông tin về cách mô tả các yếu tố, thư viện luồng có thể cung cấp cho bạn càng nhiều chức năng và hiệu suất. Theo thứ tự ít nhất cho hầu hết các thông tin, chúng là:
Lặp lại
Lặp lại + kích thước
Bộ chia tín hiệu
Spliterator biết kích thước của nó
Bộ chia tín hiệu biết kích thước của nó và biết thêm rằng tất cả các phân chia phụ đều biết kích thước của chúng.
(Một số người có thể ngạc nhiên khi thấy rằng chúng ta có thể trích xuất song song ngay cả từ một trình lặp câm trong trường hợp Q (công việc trên mỗi phần tử) là không cần thiết.)
Nếu Iterable có phương thức stream (), nó sẽ chỉ bọc Iterator bằng Spliterator, không có thông tin kích thước. Nhưng, hầu hết những thứ có thể lặp lại đều có thông tin kích thước. Điều đó có nghĩa là chúng tôi đang phục vụ các luồng thiếu. Điều đó không tốt lắm.
Một nhược điểm của thực tiễn API được Stephen nêu ra ở đây, khi chấp nhận Iterable thay vì Collection, là bạn đang buộc mọi thứ thông qua một "ống nhỏ" và do đó loại bỏ thông tin kích thước khi nó có thể hữu ích. Điều đó tốt nếu tất cả những gì bạn đang làm là bỏ qua nó, nhưng nếu bạn muốn làm nhiều hơn, sẽ tốt hơn nếu bạn có thể lưu giữ tất cả thông tin bạn muốn.
Mặc định được cung cấp bởi Iterable sẽ thực sự là một thứ vớ vẩn - nó sẽ loại bỏ kích thước mặc dù đại đa số các Iterables đều biết thông tin đó.
Mâu thuẫn?
Mặc dù, có vẻ như cuộc thảo luận dựa trên những thay đổi mà Nhóm chuyên gia đã thực hiện đối với thiết kế ban đầu của Luồng ban đầu dựa trên các trình vòng lặp.
Mặc dù vậy, thật thú vị khi nhận thấy rằng trong một giao diện như Collection, phương thức stream được định nghĩa là:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Đó có thể là chính xác cùng mã được sử dụng trong giao diện Iterable.
Vì vậy, đây là lý do tại sao tôi nói câu trả lời này có thể không thỏa đáng, nhưng vẫn thú vị cho cuộc thảo luận.
Bằng chứng tái cấu trúc
Tiếp tục với phân tích trong danh sách gửi thư, có vẻ như phương thức splitIterator ban đầu có trong giao diện Bộ sưu tập, và tại một số điểm vào năm 2013, họ đã chuyển nó lên Iterable.
Kéo splitIterator lên từ Collection sang Iterable .
Kết luận / Lý thuyết?
Sau đó, rất có thể việc thiếu phương thức trong Iterable chỉ là một thiếu sót, vì có vẻ như họ cũng nên chuyển phương thức stream khi họ chuyển splitIterator lên từ Collection sang Iterable.
Nếu có những lý do khác không rõ ràng. Ai đó có lý thuyết khác?