Hướng dẫn Java 8 Streams với các ví dụ về mã

Trong bài đăng trên blog này, chúng ta sẽ thảo luận về các tính năng của Java 8 Streams và cung cấp rất nhiều ví dụ về mã khác nhau.

Java Streams mang đến lập trình chức năng cho java và chúng được hỗ trợ bắt đầu từ java 8, vì vậy nếu bạn có phiên bản java cũ hơn, thì bạn phải nâng cấp lên java 8 để sử dụng Java Streams.



Tại sao sử dụng Java Streams?

Một số ưu điểm của luồng:


  • Luồng sẽ giúp bạn trở thành một lập trình viên java hiệu quả hơn (bạn sẽ thấy rằng với rất ít dòng mã, bạn thực sự có thể đạt được khá nhiều điều bằng cách sử dụng luồng).
  • Họ sử dụng nhiều các biểu thức lambda là một loại hàm dùng một lần.
  • ParallelStreams cho phép các hoạt động đa luồng cho các tập dữ liệu lớn rất dễ dàng.


Đường ống phát trực tiếp

Trong hầu hết các trường hợp, một đường dẫn luồng bao gồm

  • nguồn (nơi dữ liệu của bạn chảy ra ngoài)
  • theo sau là 0 hoặc nhiều hơn hoạt động trung gian
  • và một hoạt động thiết bị đầu cuối

Java Streams - Lọc, Bản đồ, Giảm


Nguồn sẽ truyền một luồng các phần tử.

Luồng các phần tử đó có thể được lọc, sắp xếp, hoặc nó có thể được ánh xạ hoặc các chuỗi hoạt động khác được áp dụng cho mỗi phần tử.

Khi kết thúc, nó có thể được thu thập hoặc giảm bớt hoặc một số thao tác đầu cuối khác nhưng chỉ thực hiện một thao tác đầu cuối.

Nguồn luồng

Nguồn luồng có thể đến từ các tập hợp, danh sách, tập hợp, mảng int, longs, double, string, v.v.


Hoạt động phát trực tiếp

Luồng hoạt động là trung gian hoặc thiết bị đầu cuối:

  • Hoạt động trung gian chẳng hạn như bộ lọc, bản đồ hoặc sắp xếp trả về một luồng để chúng tôi có thể xâu chuỗi nhiều hoạt động trung gian.
  • Hoạt động đầu cuối nhận một luồng và chúng có thể trả về giá trị vô hiệu hoặc chúng có thể trả về một kết quả không phải là luồng, chẳng hạn như giảm, ví dụ: giảm các mục vào một danh sách.

Hoạt động trung gian

  • Không cho phép hoạt động trung gian hoặc nhiều hơn.
  • Các vấn đề đặt hàng; cho các tập dữ liệu lớn: lọc đầu tiên sau đó sắp xếp hoặc lập bản đồ.
  • Đối với các tập dữ liệu rất lớn, chúng tôi ParallelStream để kích hoạt nhiều luồng.

Một số hoạt động trung gian bao gồm:

  • anyMatch ()
  • khác biệt ()
  • bộ lọc ()
  • findFirst ()
  • Bản đồ phẳng()
  • bản đồ()
  • nhảy()
  • đã sắp xếp ()

Hoạt động đầu cuối

Chỉ được phép sử dụng một thao tác đầu cuối.

  • forEach áp dụng cùng một chức năng cho mỗi phần tử, ví dụ in từng phần tử.
  • thu thập lưu tất cả các phần tử vào một tập hợp hoặc một danh sách hoặc một mảng.
  • tất cả các tùy chọn khác giảm luồng thành một phần tử tóm tắt duy nhất.

Một số ví dụ về hàm giảm là:


  • đếm()
  • max ()
  • min ()
  • giảm()


Ví dụ về mã luồng Java

Bây giờ chúng ta hãy xem các khái niệm trên trong các ví dụ mã.

Luồng số nguyên

Ví dụ đầu tiên chỉ là một luồng số nguyên. Chúng ta sẽ tạo một luồng số nguyên bằng cách sử dụng IntStream lớp và hàm phạm vi của nó cung cấp cho chúng ta một phạm vi số nguyên.

forEach là hoạt động đầu cuối của chúng tôi. Đối với mỗi mục, chúng tôi sẽ in nó ra.

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream

.range(1, 10)

.forEach(System.out::print);
System.out.println();
} }

Đầu ra:


123456789

Luồng số nguyên với Bỏ qua

Ví dụ thứ hai sử dụng một luồng số nguyên nhưng chúng tôi đã thêm một skip() ở đây, vì vậy trong trường hợp này, chúng tôi sẽ bỏ qua 5 yếu tố đầu tiên trong luồng của chúng tôi.

Điều này sẽ chỉ in các phần tử từ 6 đến 9. Chúng tôi cũng đang sử dụng một biểu thức lambda đơn giản để in mục

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream

.range(1, 10)

.skip(5)

.forEach(x -> System.out.println(x));
System.out.println();
} }

Đầu ra:

6 7 8 9

Luồng số nguyên với tổng

Ví dụ thứ ba, chúng ta lại sử dụng dấu IntStream Tuy nhiên, để tạo luồng đối tượng của chúng tôi, chúng tôi đặt nó bên trong dấu println() câu lệnh làm tham số cho dòng in.


Những gì chúng ta sẽ in chỉ là tổng từ phạm vi 1 đến 5, nói cách khác, 1 2 3 & 4 sẽ chỉ in ra tổng của những số đó:

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
System.out.println(
IntStream

.range(1, 5)

.sum());
System.out.println();
} }

Đầu ra:

10

Dòng

Ví dụ tiếp theo sử dụng dấu Stream.of , điều này thực sự tiện dụng vì bạn có thể truyền trực tuyến số nguyên, giá trị dấu phẩy động hoặc chuỗi hoặc thậm chí các đối tượng.

Trong ví dụ này, chúng ta chỉ sắp xếp theo thứ tự bảng chữ cái thẳng hàng, sau đó chúng ta sẽ tìm mục đầu tiên bằng cách sử dụng findFirst() chức năng. Sau đó, chúng tôi chỉ in ra mục đầu tiên trong danh sách.

import java.io.IOException; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream.of('Ava', 'Aneri', 'Alberto')

.sorted()

.findFirst()

.ifPresent(System.out::println);
} }

Đầu ra

Alberto

Truyền từ Mảng, sắp xếp, lọc và in

Trong ví dụ tiếp theo, chúng ta sẽ phát trực tiếp từ một mảng. Sau đó, chúng tôi sẽ sắp xếp, lọc và sau đó in.

Ở đây, chúng tôi sẽ chỉ lọc ra các mục bắt đầu bằng s.

Chúng tôi sử dụng một biểu thức lambda nhận vào X đó là mỗi tên và sau đó nó kiểm tra tên nào bắt đầu bằng chữ cái s và nó sẽ truyền lại những điều đó.

Sau đó, chúng tôi sẽ sắp xếp chúng và sau đó đối với mỗi mục vượt qua phân loại đó, chúng tôi sẽ in nó.

import java.io.IOException; import java.util.Arrays; public class JavaStreams {
public static void main(String[] args) throws IOException {
String[] names = {'Al', 'Ankit', 'Kushal', 'Brent', 'Sarika', 'amanda', 'Hans', 'Shivika', 'Sarah'};
Arrays.stream(names)


.filter(x -> x.startsWith('S'))


.sorted()


.forEach(System.out::println);
} }

Đầu ra:

Sarah Sarika Shivika

Trung bình của Mảng số nguyên

Bây giờ chúng ta hãy xem cách chúng ta có thể lấy giá trị trung bình của các ô vuông của một mảng int.

Ở đây, chúng tôi sử dụng dấu Arrays.stream() hàm để truyền các số nguyên và sau đó chúng ta sẽ sử dụng map() để ánh xạ từng mục, từng số nguyên thành hình vuông của nó.

import java.util.Arrays; public class JavaStreams {
public static void main(String[] args) {
Arrays.stream(new int[] {2, 4, 6, 8, 10})


.map(x -> x * x)


.average()


.ifPresent(System.out::println);
} }

Đầu ra:

44.0

Lưu ý rằng nó in ra gấp đôi thay vì một số nguyên.

Phát trực tiếp từ Danh sách, lọc và in

Trong ví dụ này, chúng tôi sẽ phát trực tuyến từ một danh sách, lọc các mục đó và sau đó in.

Lưu ý rằng trong dấu map() , chúng ta sẽ chuyển đổi tất cả các tên thành chữ thường.

import java.util.Arrays; import java.util.List; public class JavaStreams {
public static void main(String[] args) {
List people = Arrays.asList('Al', 'Ankit', 'Brent', 'Sarika', 'amanda', 'Hans', 'Shivika', 'Sarah');
people


.stream()


.map(String::toLowerCase)


.filter(x -> x.startsWith('a'))


.forEach(System.out::println);
} }

Đầu ra:

al ankit amanda

Chúng ta có thể thấy chúng ta có ba tên bắt đầu bằng a và chúng đều là chữ thường.

Truyền các hàng từ tệp văn bản, sắp xếp, lọc và in

Trong ví dụ tiếp theo của chúng tôi, chúng tôi sẽ truyền trực tuyến các hàng từ một tệp văn bản. Chúng tôi sẽ sắp xếp, lọc và in.

Giả sử chúng ta có một tệp có tên bands.txt với nội dung hiển thị bên dưới:

Rolling Stones Lady Gaga Jackson Browne Maroon 5 Arijit Singh Elton John John Mayer CCR Eagles Pink Aerosmith Adele Taylor Swift

Chúng tôi sẽ sử dụng Files.lines() để tạo luồng của chúng tôi sẽ cung cấp cho chúng tôi một luồng một chuỗi cho mỗi dòng của tệp.

Khi chúng tôi có luồng của mình, chúng tôi sẽ sắp xếp chúng và chúng tôi sẽ lọc ra các mục lớn hơn 13 ký tự và sau đó in các mục còn lại.

Cuối cùng, chúng ta phải đóng tệp để làm bands.close.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream bands = Files.lines(Paths.get('bands.txt'));
bands


.sorted()


.filter(x -> x.length() > 13)


.forEach(System.out::println);
bands.close();
} }

Đầu ra:

Jackson Browne Rolling Stones

Chúng tôi nhận được hai dải có hơn 13 ký tự.

Truyền các hàng từ tệp văn bản và lưu vào Danh sách

Đối với ví dụ này, chúng tôi sẽ sử dụng cùng một tệp văn bản như trên.

Chúng tôi muốn lọc ra các mục có chứa các ký tự jit, bằng cách sử dụng x.contains() mà chỉ là một hàm chuỗi.

Sử dụng dấu .collect() chúng ta thêm tất cả những cái có chữ cái jit vào một danh sách.

Khi chúng ta có danh sách, chúng ta có thể sử dụng forEach toán tử để in các mục.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; public class JavaStreams {
public static void main(String[] args) throws IOException {
List bands2 = Files.lines(Paths.get('bands.txt'))


.filter(x -> x.contains('jit'))


.collect(Collectors.toList());
bands2.forEach(x -> System.out.println(x));
} }

Đầu ra:

Arijit Singh

Truyền trực tuyến các hàng từ tệp CSV và đếm

Trong ví dụ này, chúng tôi truyền trực tuyến các hàng từ tệp CSV và chúng tôi sẽ đếm các hàng tốt.

Giả sử chúng ta có một tệp có tên là data.txt với các nội dung sau:

A,12,3.7 B,17,2.8 C,14,1.9 D,23,2.7 E F,18,3.4

Ở đây, hàng E không có dữ liệu, vì vậy chúng tôi muốn loại trừ hàng đó khỏi luồng của mình.

Trong đoạn mã sau, chúng ta sẽ đọc trong mỗi hàng, sau đó chúng ta cần tách các dấu phẩy thành một mảng để mỗi hàng sẽ trở thành một mảng các mục.

Sau đó, chúng tôi áp dụng bộ lọc để lọc ra các hàng không có ba mục.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream rows1 = Files.lines(Paths.get('data.txt'));
int rowCount = (int)rows1


.map(x -> x.split(','))


.filter(x -> x.length == 3)


.count();
System.out.println(rowCount + ' rows.');
rows1.close();
} }

Đầu ra:

5 rows

Giảm - tổng

Ví dụ này cho bạn thấy làm thế nào để sử dụng giảm. Chúng tôi sẽ giảm xuống một tổng. Ở đây, chúng ta có một luồng kép bằng cách sử dụng Stream.of() chức năng. Chúng tôi đã xác định ba giá trị nhân đôi trong ba đối số khác nhau và chúng tôi sẽ sử dụng hàm giảm.

import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) {
double total = Stream.of(7.3, 1.5, 4.8)


.reduce(0.0, (Double a, Double b) -> a + b);
System.out.println('Total = ' + total);
} }

Đầu ra:

13.600000000000001