Làm thế nào để hiểu phương thức thu thập luồng Java 8 này?


12

Tôi đã cố gắng chuyển đổi một mảng int thành List và tôi đã sử dụng lộ trình lạ khi sử dụng Java 8 Stream và đã đưa ra điều này

Arrays.stream(arr).boxed().collect(Collectors.toList());

Tôi vẫn gặp khó khăn để hiểu đầy đủ về dòng này, chủ yếu,

  1. Tại sao Collectors.toList()trong trường hợp này trả về một giao diện ArrayList<Integer>thực hiện List? Tại sao không LinkedList<Integer>hoặc bất kỳ lớp chung nào khác phù hợp với Listgiao diện? Tôi không thể tìm thấy bất cứ điều gì về điều này, ngoại trừ việc đề cập ngắn gọn về ArrayList ở đây , trong phần Ghi chú API.

  2. Bảng điều khiển bên trái có nghĩa là gì? Rõ ràng là loại trả về chung ( trong mã của tôi ở đây). Và tôi nghĩ là đối số kiểu chung của phương thức, nhưng chúng được chỉ định như thế nào? Tôi đã xem tài liệu giao diện Collector và không thể tiếp thu nó.nhập mô tả hình ảnh ở đây Stream.collect()RArrayList<Integer><R, A>


2
1. Nó sử dụng một danh sách thực tế dưới mui xe, rõ ràng. Nhưng nó sẽ không khôn ngoan khi API tiết lộ loại Danh sách cơ bản thực tế. Kể từ đó, họ không bao giờ có thể thay đổi việc thực hiện nữa trong tương lai. Nói chung, thường chỉ nên trưng ra các giao diện và không bao giờ là loại cơ bản thực tế. 2. Rlà loại chung của loại kết quả. Aloại chung của loại tích lũy trung gian của Collector. Đó là chi tiết triển khai về cách thức hoạt động của một bộ sưu tập. Nó phân chia và chinh phục, cũng để xử lý song song, thu thập đầu tiên thành các loại trung gian.
Zabuzard

10
Bạn gần như không bao giờ thực sự muốn LinkedList. Có một tweet của Josh Bloch , nói rằng "Tôi đã viết nó, và tôi không bao giờ sử dụng nó".
Andy Turner

4
"Tại sao Collectors.toList()trong trường hợp này trả về ArrayList<Integer>" Nó có thể không trả về ArrayList. Việc Listtriển khai không được xác định , vì vậy bạn không thể dựa vào việc triển khai nó trả về. Như javadoc nói: "Không có gì đảm bảo về loại , tính dễ biến đổi, tính tuần tự hoặc tính an toàn của luồng của Danh sách được trả về;"
Andreas

3
toList()sẽ không trả lại một ArrayListhoặc List- nó đang trả lại một Collector, cuối cùng sẽ tạo và trả về một List- cũng là tài liệu nêu rõ: "... Không có gì đảm bảo về loại , tính biến đổi, tính tuần tự hoặc tính an toàn của danh sách được trả về; nếu cần thêm quyền kiểm soát Danh sách được trả lại, hãy sử dụng toCollection (Nhà cung cấp) .... "
user85421-Cấm

3
Tôi thực sự khuyên bạn nên tài liệu gói
Holger

Câu trả lời:


18
  1. Đó là một triển khai mặc định. ArrayListđược sử dụng, bởi vì nó tốt nhất trong hầu hết các trường hợp sử dụng, nhưng nếu nó không phù hợp với bạn, bạn luôn có thể xác định bộ sưu tập của riêng mình và cung cấp nhà máy cho Collectionbạn muốn:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. Có, ARlà các tham số chung của phương thức này, Rlà kiểu trả về, Tlà kiểu đầu vào và Alà loại trung gian, xuất hiện trong toàn bộ quá trình thu thập các phần tử (có thể không hiển thị và không liên quan đến chức năng này). Phần đầu của Collectorjavadoc định nghĩa các loại đó (chúng nhất quán trên toàn bộ tài liệu):

    T - loại phần tử đầu vào cho hoạt động khử
    A - loại tích lũy có thể thay đổi của hoạt động giảm (thường được ẩn dưới dạng chi tiết triển khai)
    R - loại kết quả của hoạt động giảm


Ok tôi hiểu rồi. Tôi đoán tôi thực sự nên bám vào List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());và chỉ gọi các phương thức được khai báo trong giao diện List trên myList. Mặt khác, tôi có khả năng tự đặt mình vào rủi ro, nếu Oracle quyết định thay đổi triển khai mặc định trong Java8u1024 hoặc 15?
dùng3207158

2
@ user3207158 phương thức trả về a List, do đó, bất kỳ triển khai nào được sử dụng, hành vi đều giống nhau. Giao diện sẽ không được thay đổi trong các phiên bản java mới hơn.
Andronicus

1
  1. Tại sao Collector.toList () trong trường hợp này trả về giao diện Danh sách triển khai ArrayList?

Như định nghĩa phương thức cho thấy nó trả về một triển khai Collector với nhà cung cấp collector là ArrayList. Do đó, rất rõ ràng từ định nghĩa phương thức bên dưới Collectors.toListluôn trả về trình thu thập ArrayList ( While it's arguable why toList not toArrayList word is used in method name).

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. Bảng điều khiển bên trái <R, A> R collect(Collector<? super T, A, R> collector)có nghĩa là gì

Nếu bạn tham khảo ý kiến ​​tài liệu, nó đề cập chính xác những loại chung này là gì:

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);

Cảm ơn ngài. Bạn lấy mã nguồn của Collectors.toList()(đoạn đầu tiên) ở đâu? Có phải openjdk?
dùng3207158

1
Không! Tôi đã tải xuống mã nguồn trong intelli j
Vinay Prajapati
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.