Chúng ta bắt đầu bằng việc cắt nghĩa một từ tiếng Anh. Từ “stream” bạn tạm hiểu/liên tưởng đó là “dòng nước”, “dòng suối”, “luồng”. Một stream (“dòng”) là tuần tự dữ liệu hỗ trợ các thao tác tổng hợp tuần tự, cho phép xử lý song song.
Chúng ta thường sử dụng các hàm tính tổng trong SQL khá thường xuyên. Chẳng hạn tính tổng giá trị hàng bán được trong 1 tháng, gọi là doanh thu trong tháng. Hoặc lấy giá trị số lớn nhất trong chuỗi số.
Kết quả của một thao tác tổng trên stream có thể trả về kiểu dữ liệu nguyên thủy, một đối tượng hoặc không trả về kết quả (void). Với stream, chúng ta có thể tính tổng tất cả các số nguyên của một dòng các số nguyên.
Bài toán: Tính tổng bình phương các số chẵn từ 1 đến 10.
Trước Java 8, chúng ta viết code như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package com.smartJob.demo;
import java.util.Arrays;
import java.util.List;
public class SumCalculator {
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = 0;
for (int n : numbers) {
if (n % 2 == 0) {
int square = n * n;
sum = sum + square;
}
}
System.out.println(sum);
}
}
// Kết quả:
//run:
//220
//BUILD SUCCESSFUL (total time: 0 seconds)
|
Kết quả: sum = 2*2 + 4*4 + 6*6 + 8*8 + 10*10 = 220.

Dòng suối (stream)
Với Java 8, sử dụng stream chúng ta viết như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.smartJob.demo;
import java.util.Arrays;
import java.util.List;
public class SumCalculator2 {
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.stream()
.filter(n –> n % 2 == 0)
.map(n –> n * n)
.reduce(0, Integer::sum);
System.out.println(sum);
}
}
// Kết quả:
//run:
//220
//BUILD SUCCESSFUL (total time: 0 seconds)
|

Tổng lưu lượng nước sẽ lớn hơn nếu đi theo nhiều dòng – parallel stream
Để tận dụng sức mạnh của xử lý song song, chúng ta sử dụng cú pháp Java 8 với phương thức parallelStream() như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.smartJob.demo;
import java.util.Arrays;
import java.util.List;
public class SumCalculator3 {
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.parallelStream()
.filter(n –> n % 2 == 0)
.map(n –> n * n)
.reduce(0, Integer::sum);
System.out.println(sum);
}
}
// Kết quả:
//run:
//220
//BUILD SUCCESSFUL (total time: 0 seconds)
|
SmartJob đã giới thiệu bạn ba cách để giải quyết một vấn đề. Một cách của ngày xưa, hai cách sử dụng cú pháp Java 8. Ưu điểm của streams API là cú pháp ngắn gọn hơn một chút, gần với ngôn ngữ tự nhiên hơn.
Một số ví dụ minh họa khác:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package com.smartJob.demo;
import java.util.stream.Stream;
public class StreamExample1 {
public static void main(String[] args) {
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.parallel()
.map(s –> s.toString())
.map(s –> s + ” “)
.forEach(System.out::print);
}
}
// Kết quả:
//run:
//7 6 9 10 8 3 5 4 2 1 BUILD SUCCESSFUL (total time: 0 seconds)
|
So sánh độ dài của xâu ký tự:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package com.smartJob.demo;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class StreamExample2 {
public static void main(String[] args) {
List list = Arrays.asList(“Hoàng Thế Anh”, “Nguyễn Văn Còn”, “Đoàn Minh Huệ”, “Phạm Văn Đoan”);
list
// Chuyển danh sách (list) thành dòng (stream).
.stream()
// Chuyển các ký tự về dạng viết hoa.
.map(String::toUpperCase)
// So sánh độ dài của các xâu (String). Tìm ra xâu có độ dài lớn nhất.
.max(Comparator.comparing(String::length))
// Nếu tồn tại xâu có độ dài lớn nhất (ifPresent: nếu có mặt/hiện diện), thì in ra.
.ifPresent(System.out::println);
}
}
// Kết quả:
//run:
//NGUYỄN VĂN CÒN
//BUILD SUCCESSFUL (total time: 0 seconds)
|
Đếm số nhân viên của SmartJob từ 24 tuổi trở lên
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
package com.smartJob.demo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamExample3 {
public static void main(String[] args) {
Employee e1 = new Employee(“Nguyễn Vân Anh”, 25, “Quản trị nguồn nhân lực”);
Employee e2 = new Employee(“Phạm Văn Đoan”, 32, “PHP”);
Employee e3 = new Employee(“Nguyễn Văn Dũng”, 23, “PHP”);
Employee e4 = new Employee(“Nguyễn Văn Bắc”, 24, “SEO”);
// Tạo danh sách (list) gồm 4 nhân viên đã khởi tạo ở trên.
List employeeList = Arrays.asList(e1, e2, e3, e4);
// Tạo cấu trúc dữ liệu map.
Map<Integer, Long> from24YearsOld = employeeList.stream().parallel()
// Lọc ra các nhân viên từ 24 tuổi trở lên mới thêm vào map.
.filter(
employee –> employee.getAge() >= 24
)
// Nhóm lại theo độ tuổi.
.collect(
Collectors.groupingBy(Employee::getAge, Collectors.counting())
);
// Kích thước (số phần tử) của map, cũng là số nhân viên từ 24 tuổi trở lên.
System.out.println(“Số lượng nhân viên từ 24 tuổi trở lên là: “ + from24YearsOld.size());
}
}
/**
* Thực thể “Nhân viên”.
*/
class Employee {
// Tên nhân viên.
private String fullname;
// Tuổi.
private int age;
// Kỹ năng/chuyên môn chính.
private String mainSkill;
public Employee() {
}
public Employee(String fullname, int age, String mainSkill) {
this.fullname = fullname;
this.age = age;
this.mainSkill = mainSkill;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getMainSkill() {
return mainSkill;
}
public void setMainSkill(String mainSkill) {
this.mainSkill = mainSkill;
}
}
// Kết quả:
//run:
//Số lượng nhân viên từ 24 tuổi trở lên là: 3
//BUILD SUCCESSFUL (total time: 0 seconds)
|
Đếm số ký tự không trùng lặp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.smartJob.demo;
import java.util.stream.IntStream;
public class Counting {
public static void main(String[] args) {
// Có tổng số 13 ký tự.
String foo = “smartjobdotvn”;
IntStream letters = foo.chars();
long counter = letters.distinct().count();
// Nhưng chỉ có 11 ký tự sau khi loại bỏ trùng lặp.
System.out.println(“Số ký tự có mặt trong chuỗi (đã loại bỏ trùng lặp): “ + counter);
}
}
// Kết quả:
//run:
//Số ký tự có mặt trong chuỗi (đã loại bỏ trùng lặp): 11
//BUILD SUCCESSFUL (total time: 0 seconds)
|
Project để bạn tải về: Java8_stream
Đỗ Như Vý – developer tại SmartJob
java,
Java 8,
streams,