2014-04-01 20 views
9

tôi đã tự hỏi về Java 8 suối (Stream<E>), họ có các phương pháp sau:Lý do không có chỉ mục trong luồng Java 8 là gì?

  • forEach(Consumer<? super E> action)
  • forEachOrdered(Consumer<? super E> action)

những lập luận chống lại không cung cấp chữ ký sau đây là gì?

  • forEachOrdered(BiConsumer<Integer, ? super E> action)
    • Mà sau đó sẽ trở lại chỉ số của mặt hàng đó trong dòng và mục riêng của mình.

Với quá tải này, bạn có thể sử dụng chỉ mục trong trường hợp luồng được đặt hàng.

Tôi thực sự tò mò muốn biết những gì các đối số chống lại nó.

Chỉnh sửa, cùng thực tế giữ cho Iterator<E> với forEachRemaining và có thể nhiều lớp hơn.
Nếu không có lớp nào cung cấp tùy chọn như vậy, thì tôi nghi ngờ nó đã được xem xét cho Java 8 và bị từ chối.

+0

http://stackoverflow.com/a/18563928/829571 – assylias

+0

@assylias Cảm ơn bạn đã cắm phích cắm. Điều đó khiến tôi phải dọn dẹp câu trả lời đó. :-) –

Trả lời

5

Stream s và Iterator s không nhất thiết phải hữu hạn. Cả hai Stream::generateStream::iterate trả về vô hạn Stream s. Bạn sẽ xử lý lập chỉ mục bằng luồng vô hạn như thế nào? Để cho chỉ mục tràn đến các số âm? Sử dụng BigInteger (và có khả năng hết bộ nhớ)?

Không có giải pháp tốt để xử lý lập chỉ mục cho các luồng vô hạn, do đó, các nhà thiết kế (đúng, theo ý kiến ​​của tôi) đã bỏ nó ra khỏi API.

+3

Vấn đề tương tự xảy ra với 'Collectors.counting()', có một 'long' được sử dụng, nhưng nó có thể tràn ra ngoài. Vì vậy, vào thời điểm đó, hoặc đối số của bạn là không đủ tốt, hoặc nó là một đối số tốt chống lại 'Collectors.counting()' là tốt. Tôi không thấy bất kỳ vấn đề nào khác mặc dù với các luồng và vòng lặp vô hạn (ngoài việc chúng không bao giờ dừng lại) – skiwi

+1

@skiwi Vâng, nếu bạn đã cố gắng sử dụng một nửa các phương thức trong 'Bộ sưu tập' trên một' Stream' vô hạn, bạn sẽ chạy hết bộ nhớ hoặc giới thiệu một vòng lặp vô hạn. 'Bộ sưu tập' cung cấp các phương thức tiện ích để xử lý phần lớn các trường hợp sử dụng. Hầu hết thời gian, bạn sẽ không thực sự được giao dịch với một 'Stream' vô hạn, do đó, 'Collectors' được bảo hành. – Jeffrey

8

lập chỉ mục mọi phần tử yêu cầu phân bổ tuần tự các chỉ mục. điều này sẽ đánh bại điểm của các hoạt động song song, vì mỗi thao tác sẽ phải đồng bộ hóa để lấy chỉ mục của nó.

+0

+1. Các chỉ mục là vô nghĩa đối với các luồng song song. –

+1

Tôi đang nói cụ thể về luồng đặt hàng, nếu bạn quyết định đứng bằng câu trả lời của mình, bạn có thể giải thích tại sao không thể lập chỉ mục trong luồng được đặt hàng song song không? – skiwi

+0

Nếu bạn muốn, bạn có thể giữ một truy cập trong chính người tiêu dùng cho các hoạt động được biết là được thực thi theo thứ tự, vậy tại sao bạn cần thêm chữ ký? –

2

Việc thêm một phương pháp cung cấp chỉ mục sẽ yêu cầu tất cả các phương pháp triển khai phải được tăng gấp đôi để có chỉ mục duy trì chỉ mục và chỉ số không có chỉ mục. Có nhiều điều hơn là hiển thị trong API. Nếu bạn tò mò, bạn có thể xem loại cây của giao diện nội bộ java.util.stream.Sink<T> để có ý tưởng. Tất cả chúng sẽ bị ảnh hưởng. Cách thay thế sẽ là luôn duy trì một chỉ mục ngay cả khi nó không được yêu cầu.

Và nó thêm một sự mơ hồ. Chỉ mục có phản ánh chỉ số nguồn, tức là không thay đổi về lọc hay là một vị trí trong luồng cuối cùng? Mặt khác, bạn luôn có thể chèn ánh xạ từ loại mục vào loại giữ mục và chỉ mục tại bất kỳ vị trí nào trong chuỗi. Điều này sẽ làm rõ sự mơ hồ. Và những hạn chế đối với giải pháp đó là giống như một giải pháp được cung cấp JRE sẽ có.

Trong trường hợp Iterator câu trả lời thậm chí còn đơn giản hơn. Vì forEachRemaining phải được cung cấp dưới dạng phương thức giao diện default, nó không thể thêm việc duy trì chỉ mục.Vì vậy, tại thời điểm nó được gọi, nó không biết có bao nhiêu mặt hàng đã được tiêu thụ cho đến nay. Và bắt đầu đếm với số không tại thời điểm đó, bỏ qua tất cả các mục trước đó sẽ là một tính năng mà rất nhiều nhà phát triển sẽ đặt câu hỏi nhiều hơn.

0

Tôi đã đọc tất cả câu trả lời ở trên, tuy nhiên, cá nhân tôi không đồng ý với họ. Tôi nghĩ rằng một số phương pháp (ví dụ như indexed()) nên được thêm vào và nó có thể được thực hiện tuần tự, ngay cả trong luồng song song vì phương pháp này sẽ được xác minh nhanh, không cần thực thi song song. Bạn có thể thêm 'chỉ mục' theo bản đồ. ví dụ:

List<String> list = N.asList("a", "b", "c"); 
final AtomicLong idx = new AtomicLong(0); 
list.stream().map(e -> Indexed.of(idx.getAndIncrement(), e)).forEach(N::println); 

Hoặc bạn có thể sử dụng thư viện thứ ba: AbacusUtil, mã sẽ là:

List<String> list = N.asList("a", "b", "c"); 
Stream.of(list).indexed().forEach(N::println); 
// output: 
// [0]=a 
// [1]=b 
// [2]=c 

Tiết lộ: Tôi là nhà phát triển của AbacusUtil.

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