12/08/2018, 14:29

Java 9 Stream API Improvements

Phiên bản tiếp theo mà Oracle sẽ phát hành vào khoảng thời gian cuối tháng 3 năm 2017 tới đây chính là Java SE 9 . Vì vậy trong bài viết này tôi muốn giới thiệu cho các bạn biết về một đặc tính cải tiến khá hay về Java SE 9 Stream API. Đầu tiên ta sẽ nói qua về Java SE 8 Stream API. Sau đó tôi ...

Phiên bản tiếp theo mà Oracle sẽ phát hành vào khoảng thời gian cuối tháng 3 năm 2017 tới đây chính là Java SE 9 . Vì vậy trong bài viết này tôi muốn giới thiệu cho các bạn biết về một đặc tính cải tiến khá hay về Java SE 9 Stream API. Đầu tiên ta sẽ nói qua về Java SE 8 Stream API. Sau đó tôi sẽ giới thiệu về những cải tiến của Java SE 9 Stream API.

Như chúng ta đã biết, 1 trong những thay đổi đáng kể được Oracle Corporation giới thiệu trong Java SE 8 chính là Stream API bên cạnh Lambda Expressions.

Vậy Stream là gì?

Stream là một chuỗi các phần tử và hỗ trợ một tập hợp các hành động một cách tổng thể. Nó hỗ trợ các toán tử nối tiếp hoặc song song theo các yêu cầu cụ thể được định nghĩa. Oracle Corp đã định nghĩa lớp Stream API mới này trong package java.util.stream. Điều quan trọng chính là nằm trong lớp interface Stream API này. Ưu điểm của Stream API là hỗ trợ việc hỗ trợ lặp trong chính bản thân nó (internal iteration). Bởi vì với đặc tính mới này của Stream API, chúng ta có thể thực hiện các toán tử một cách Lazy và Parallel.

Ví dụ thực hiện 1 vài toán tử Stream.

jshell> import java.util.stream.*

jshell> Stream stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@64bfbc86

jshell> stream.forEach(x -> System.out.println(x));
1
2
3
4
5
6
7
8
9
10

Để tìm hiểu thêm về Java SE 8 API, chúng ta có thể tham khảo tại http://www.journaldev.com/2774/java-8-stream

Trong Java SE 9, Oracle Corp đã thêm 4 method mới trong interface java.util.Stream.

  • dropWhile
  • takeWhile
  • iterate
  • ofNullable

Trong lớp giao diện Stream mới này thì 2 method đầu tiên sẽ là 2 method mặc định và khá quan trọng (dropWhile, takeWhile ), còn lại sẽ là 2 static methods.

Trong Stream API, method takeWhile() trả về các phần tử được matche mới điều kiện vị ngữ (Predicate condition). Một Predicate là biểu thức Boolean, chúng sẽ trả về các giá trị true hoặc false. Và phụ thuộc vào 1 Stream đã được sắp xếp hay chưa mà ta sẽ có các đầu ra kết quả khác nhau.

Stream API:

default Stream<T> takeWhile(Predicate<? super T> predicate)

Nếu Stream đã được sắp xếp, method takeWhile() sẽ cho ra các chuỗi các phần tử dài nhất matche vs điều kiện vị ngữ (Predicate condition), khác với việc kết quả trả về của Stream chứa các phần tử matche với điều kiện xét.

Ordered Stream Example:

jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2
3

Như trong Stream đã được sắp xếp trên thì takeWhile() trả về 3 phần tử đầu tiên matche với điều kiện mà ta đang xét.

Unordered Stream Example:

jshell> Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2

Kết quả chỉ trả về 2 phần tử cho 1 Stream không được sắp xếp. Điều này có nghĩa rằng takeWhile() trả về tất cả các phần tử cho đến khi chúng match được với điều kiện. Khi điều kiện rơi vào điều kiện false ngay từ phần nào đó. Nó sẽ dừng lại và trả về chuỗi phần tử con của Stream đó.

Trong Stream API, method dropWhile() trả về lượng phần tử lớn nhất lượng phần tử còn sót lại sau khi matche với điều kiện xét.

Stream API:

default Stream<T> dropWhile(Predicate<? super T> predicate)

Tương tự như method takeWhile thì dropWhile sẽ cho ra kết quả khác nhau với các Stream được sắp xếp hay không sắp xếp.

Ordered Stream Example:

jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a))
4
5
6
7
8
9
10

Unordered Stream Example:

jshell> Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a))
4
5
3
6
7
8
9
10

Điều này có nghĩa rằng , method dropWhile sẽ lấy các phần tử còn xót lại sau khi bỏ đi chuỗi các pần tử matche với điều kiện xét.

Trong Stream API, method iterate() trả về chuỗi các phần tủ bắt đầu xét điều kiện từ vị trí nhất định (first parameter) matches với điều kiện và trả về chuỗi phần tử phù hợp.

Stream API:

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

Nó giống như là 1 vòng lặp: đối số đầu tiên dùng để khởi tạo giá trị, đối số tiếp theo là điều kiện xét và đối sô cuối dùng dùng để sinh ra các phần tử phù hợp tiếp theo (toán tử tăng hoặc giảm).

Java SE 9 IntStream iterate Example:

jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
 Java SE 9's iterate() = Java SE 8's iterate() + Java SE 8's filter()

Java SE 8: IntStream iterate and fileter Example:

jshell> IntStream.iterate(2, x -> x * x).filter(x -> x < 20).forEach(System.out::println)
2
4
16

Trong Stream API, ofNullable() trả về Stream chưá phần tử nếu phần tử đó not null, còn không nó sẽ trả về empty Stream.

Java SE 9 Example:

jshell> Stream<Integer> s = Stream.ofNullable(1)
s ==> java.util.stream.ReferencePipeline$Head@1e965684

jshell> s.forEach(System.out::println)
1

jshell> Stream<Integer> s = Stream.ofNullable(null)
s ==> java.util.stream.ReferencePipeline$Head@3b088d51

jshell> s.forEach(System.out::println)

jshell> 

NOTE: Các sub-interfaces của Stream (giống như IntStream, LongStream ) được kế thừa từ 4 method trên. Trên đây là những điểm mới cải tiến của Java SE 9: Stream API . Chúng ta sẽ bàn thêm về nó trong các bài viết tiếp theo.

0