2015-04-22 24 views
5

Tôi đã đọc trên các luồng Java 8 và cách dữ liệu được truyền trực tiếp từ nguồn dữ liệu, thay vì có toàn bộ bộ sưu tập để trích xuất dữ liệu.Dòng Java 8 vs Bộ sưu tập Bộ sưu tập

quote này nói riêng tôi đọc trên một bài báo liên quan đến con suối trong Java 8.

"Không lưu trữ Streams không có lưu trữ cho các giá trị;. Họ mang giá trị từ một nguồn (mà có thể là một cấu trúc dữ liệu, một hàm tạo ra, một kênh I/O, vv) thông qua một đường dẫn của các bước tính toán. " Từ nguồn: http://www.drdobbs.com/jvm/lambdas-and-streams-in-java-8-libraries/240166818?pgno=1

Tôi hiểu khái niệm về truyền dữ liệu từ nguồn từng mảnh. Điều tôi không hiểu là nếu bạn đang phát trực tuyến từ bộ sưu tập thì không có bộ nhớ nào? Bộ sưu tập đã tồn tại trên Heap, bạn chỉ đang truyền dữ liệu từ bộ sưu tập đó, bộ sưu tập đã tồn tại trong "bộ nhớ".

Sự khác biệt về dung lượng bộ nhớ là gì nếu tôi chỉ lặp qua bộ sưu tập với tiêu chuẩn cho vòng lặp?

Trả lời

17

Thông báo về luồng và lưu trữ có nghĩa là luồng không có bất kỳ bộ nhớ nào riêng của mình. Nếu nguồn của luồng là tập hợp, thì rõ ràng là bộ sưu tập có bộ nhớ để lưu giữ các phần tử.

Hãy lấy một ví dụ từ bài viết rằng:

int sum = shapes.stream() 
       .filter(s -> s.getColor() == BLUE) 
       .mapToInt(s -> s.getWeight()) 
       .sum(); 

Giả sử rằng shapes là một Collection rằng có hàng triệu các yếu tố. Người ta có thể tưởng tượng rằng hoạt động filter sẽ lặp qua các phần tử từ nguồn và tạo ra một tập hợp các kết quả tạm thời, mà cũng có thể có hàng triệu phần tử. Các hoạt động mapToInt sau đó có thể lặp qua bộ sưu tập tạm thời đó và tạo kết quả của nó để được tổng hợp.

Đó không phải là cách nó hoạt động. Không có bộ sưu tập tạm thời, trung gian. Các hoạt động dòng được pipelined, do đó, các yếu tố nổi lên từ filter được chuyển qua mapToInt và từ đó đến sum mà không được lưu trữ và đọc từ một bộ sưu tập.

Nếu nguồn luồng không phải là bộ sưu tập - giả sử, các phần tử đã được đọc từ bộ sưu tập mạng - không cần bất kỳ bộ nhớ nào. Đường ống như sau:

int sum = streamShapesFromNetwork() 
       .filter(s -> s.getColor() == BLUE) 
       .mapToInt(s -> s.getWeight()) 
       .sum(); 

có thể xử lý hàng triệu thành phần, nhưng không cần lưu trữ hàng triệu phần tử ở bất kỳ đâu.

3

Hãy nghĩ luồng như một vòi phun được kết nối với bể chứa nước là cấu trúc dữ liệu của bạn. Vòi phun không có bộ nhớ riêng. Chắc chắn, nước (dữ liệu) luồng cung cấp đến từ một nguồn có lưu trữ, nhưng chính luồng đó không có bộ nhớ. Việc kết nối một vòi (dòng) khác với bể của bạn (cấu trúc dữ liệu) sẽ không yêu cầu lưu trữ cho một bản sao dữ liệu hoàn toàn mới.

+0

Cảm ơn bạn đã trả lời! Tôi hiểu phần truyền dữ liệu, nhưng chi phí bộ nhớ (lưu trữ) là gì nếu tôi chỉ sử dụng bộ sưu tập trực tiếp thay vì phát trực tiếp bộ nhớ đó? Nếu tôi sử dụng bộ sưu tập trực tiếp, tôi truy cập bộ sưu tập trên heap, nếu tôi phát trực tiếp bộ sưu tập đó, tôi vẫn đang truyền dữ liệu từ bộ sưu tập nằm trên heap. Dù bằng cách nào thì dấu chân bộ nhớ vẫn giống nhau trong cả hai phương pháp. Xin vui lòng sửa tôi nếu tôi sai/thiếu một cái gì đó ở đây. – user3587411

+0

@ user3587411: Về cơ bản không có sự khác biệt. Một cách có thể sử dụng một vài khung ngăn xếp và các đối tượng tạm thời, nhưng đó chỉ là một vài byte. – user2357112

+0

* "Dù cách nào thì dấu vết bộ nhớ vẫn giống nhau trong cả hai phương pháp." * Mục đích của luồng không phải là để tiết kiệm bộ nhớ. – Radiodef

3

Luồng chỉ là xem dữ liệu, không có bộ nhớ riêng và bạn không thể sửa đổi bộ sưu tập cơ bản (giả sử đó là luồng được xây dựng trên bộ sưu tập) thông qua luồng. Nó giống như truy cập "chỉ đọc".

Nếu bạn có bất kỳ trải nghiệm RDBMS nào - đó chính là ý tưởng tương tự về "chế độ xem".

0
  1. Collection là một cấu trúc dữ liệu. Dựa trên vấn đề bạn quyết định bộ sưu tập nào sẽ được sử dụng như ArrayList, LinekedList (Xem xét độ phức tạp về không gian và thời gian). Ở đâu là Luồng chỉ là một loại công cụ xử lý, giúp cuộc sống của bạn trở nên dễ dàng.

  2. Sự khác biệt khác là, bạn có thể xem xét Bộ sưu tập làm cấu trúc dữ liệu trong bộ nhớ, nơi bạn có thể thêm, xóa phần tử. Ở đâu trong số Luồng bạn có thể thực hiện hai loại hoạt động:

    a. Hoạt động trung gian: Bộ lọc, bản đồ, sắp xếp, giới hạn trên tập hợp kết quả
    b. Hoạt động đầu cuối: forEach, thu thập tập hợp kết quả thành bộ sưu tập.

    Nhưng nếu bạn nhận thấy, với luồng, bạn không thể thêm hoặc xóa các phần tử.

  3. Suối là loại iterator, bạn có thể đi qua bộ sưu tập qua suối. Lưu ý, bạn có thể đi qua suối chỉ một lần, hãy để tôi cung cấp cho bạn một ví dụ để có sự hiểu biết tốt hơn:

example1:

List<String> employeeNameList = Arrays.asList("John","Peter","Sachin"); 
    Stream<String> s = employeeNameList.stream(); 

    // iterate through list 
    s.dorEach(System.out :: println); // this work's perfectly fine 
    s.dorEach(System.out :: println); // you will get IllegalStateException, stating stream already operated upon 

Vì vậy, những gì bạn có thể suy ra là, bộ sưu tập, bạn có thể lặp lại càng nhiều số lần bạn muốn. Nhưng đối với luồng, một khi bạn lặp lại, nó sẽ không nhớ những gì nó được cho là phải làm. Vì vậy, bạn cần phải hướng dẫn nó một lần nữa.

Tôi hy vọng, điều đó rõ ràng.