Collections - Streams in Java 8

Java 8 Streams là một bổ sung mới vào các API Java Collections, nó mang lại một cách mới để xử lý với các Collections của đối tượng. Như vậy, Streams trong API Java Collections là một khái niệm khác hơn so với input và output streams trong Java IO API.

Streams được thiết kế để làm việc với các biểu thức lambda Java . Nhiều ví dụ trong bài viết này sẽ sử dụng các biểu thức lambda, vì vậy nếu bạn chưa biết đến nó, bạn nên tìm hiểu về biểu thức Lamda trước khi đọc bài viết này.

Vậy bạn làm như thế nào để tạo được một Stream từ Collections ?

Cách làm như sau:

List <String> mục = new ArrayList <String> ();
items.add ( "một");
items.add ( "hai");
items.add ( "ba");
Stream<String> stream = items.stream();

Lần đầu tiên một List các chuỗi được tạo ra và thêm 3 phần tử vào nó. Sau đó, một Stream thu được bằng cách gọi phương thức items.stream(). Điều này cũng tương tự như cách bạn có được một Iterator bằng cách gọi phương thức items.iterator(), nhưng một Stream là một thứ khác so với một Iterator .

1. Stream Processing Phases (các giai đoạn xử lý trong stream)

Một khi bạn đã có được một Stream từ một Collection, bạn sẽ sử dụng Stream đó để xử lý các phần tử có trong Collection.

Xử lý các phần tử trong Stream sẽ xảy ra theo 2 giai đoạn:

  • Configuration
  • Processing

Đầu tiên các Stream được cấu hình. Thực chất đây là quá trình lọc hoặc ánh xạ các phần tử trong collection. Thứ hai là Stream được xử lý. Việc xử lý bao gồm làm một việc gì đó cho các phần tử trong collection.

Một số method được Stream hỗ trợ:

a. Stream.filter()

Bạn lọc một collection bằng cách sử dụng phương thức filter(). Dưới đây là một ví dụ:

stream.filter(item -> item.startsWith("o"));

Các phương thức filter() có một Predicate như là tham số. Các Predicate interface có chứa một hàm gọi là test() mà biểu thức lambda sẽ xử dụng nó để lọc phần tử trong collection. Các test() method được định nghĩa như thế này: boolean test (T t)

Chỉ có một tham số duy nhất và trả về một boolean . Nếu bạn nhìn vào các biểu thức lambda ở trên, bạn có thể thấy rằng nó có một tham số đơn hàng và trả về một boolean - đây chính là kết quả của việc gọi item.startsWith ( "o").

b. Stream.map()

Nó có thể chuyển các phần tử trong collection từ loại object này sang 1 loại object khác. Nói cách khác, đối với từng phần tử trong collection bạn sẽ tạo một đối tượng mới dựa trên đó. Dưới đây là một ví dụ đơn giản về stream mapping trong Java:

list.stream().map(item -> item.toUpperCase());

Trong ví dụ trên thì tất cả các phần tử bên trong List sẽ được chuyển về dạng chữ hoa (uppercase).

c. Stream.collect()

Phương thức collect() là một trong những phương pháp xử lý trên Stream interface. Khi phương pháp này được gọi, filter() hay map() sẽ được diễn ra và đối tượng kết quả từ những hành động này sẽ được thu thập lại dưới dạng một collection khác. Dưới đây là một ví dụ về stream.collect():

List <String> filter = items.stream()
    .filter (item -> item.startsWith("o"))
    .collect (Collectors.toList());

Ví dụ này tạo một Stream, thêm một filter(), và collect tất cả các đối tượng được chấp nhận bởi các bộ lọc trong List . Phương thức filter chỉ chấp nhận các chuỗi mà bắt đầu với chữ "o".

d. Stream.min() và Stream.max() Phương thức min hoặc max dùng để xử lý các phần tử trong stream, nó trả về kết quả là giá trị nhỏ nhất hoặc lớn nhất

Dưới đây là một ví dụ về Stream.min():

 String shortest = items.stream()
        .min (Comparator.comparing (item -> item.length ()))
        .get();

Phương thức min, max sẽ trả về một Optional object nên bạn có thể lấy ra giá trị bằng hàm get(), nếu không nó sẽ là giá trị null;

e. Stream.count()

Đây là phương thức để đếm số lượng các phần tử có trong collection. Dưới đây là một ví dụ:

long cnt = items.stream()
     .filter (item -> item.startsWith("t"))
     .count();

Ở ví dụ trên, stream sẽ đếm xem có bao nhiêu phần tử bắt đầu bằng ký tự "t" có trong collection.