Java 8 - Luồng

Stream là một lớp trừu tượng mới được giới thiệu trong Java 8. Sử dụng stream, bạn có thể xử lý dữ liệu theo cách khai báo tương tự như các câu lệnh SQL. Ví dụ, hãy xem xét câu lệnh SQL sau.

SELECT max(salary), employee_id, employee_name FROM Employee

Biểu thức SQL ở trên tự động trả về thông tin chi tiết của nhân viên được trả lương tối đa mà không cần thực hiện bất kỳ tính toán nào từ phía nhà phát triển. Sử dụng khung công tác tập hợp trong Java, một nhà phát triển phải sử dụng các vòng lặp và thực hiện kiểm tra nhiều lần. Một mối quan tâm khác là hiệu quả; vì các bộ xử lý đa lõi có sẵn một cách dễ dàng, một nhà phát triển Java phải viết xử lý mã song song có thể dễ xảy ra lỗi.

Để giải quyết những vấn đề như vậy, Java 8 đã giới thiệu khái niệm luồng cho phép nhà phát triển xử lý dữ liệu một cách khai báo và tận dụng kiến ​​trúc đa lõi mà không cần phải viết bất kỳ mã cụ thể nào cho nó.

Stream là gì?

Luồng đại diện cho một chuỗi các đối tượng từ một nguồn, hỗ trợ các hoạt động tổng hợp. Sau đây là các đặc điểm của Luồng:

  • Sequence of elements- Một luồng cung cấp một tập hợp các phần tử của kiểu cụ thể một cách tuần tự. Luồng nhận / tính toán các phần tử theo yêu cầu. Nó không bao giờ lưu trữ các phần tử.

  • Source - Luồng lấy Bộ sưu tập, Mảng hoặc tài nguyên I / O làm nguồn đầu vào.

  • Aggregate operations - Luồng hỗ trợ các hoạt động tổng hợp như bộ lọc, bản đồ, giới hạn, giảm, tìm, so khớp, v.v.

  • Pipelining- Hầu hết các hoạt động luồng đều trả về chính luồng để kết quả của chúng có thể được kết nối. Các hoạt động này được gọi là các hoạt động trung gian và chức năng của chúng là lấy đầu vào, xử lý và trả đầu ra cho đích. Phương thức collect () là một hoạt động đầu cuối thường xuất hiện ở cuối hoạt động pipelining để đánh dấu sự kết thúc của luồng.

  • Automatic iterations - Các hoạt động luồng thực hiện lặp lại nội bộ đối với các phần tử nguồn được cung cấp, ngược lại với Bộ sưu tập khi yêu cầu lặp lại rõ ràng.

Tạo luồng

Với Java 8, giao diện Bộ sưu tập có hai phương pháp để tạo Luồng.

  • stream() - Trả về một luồng tuần tự coi bộ sưu tập là nguồn của nó.

  • parallelStream() - Trả về một Luồng song song coi tập hợp là nguồn của nó.

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

cho mỗi

Luồng đã cung cấp một phương thức mới 'forEach' để lặp lại từng phần tử của luồng. Đoạn mã sau đây cho thấy cách in 10 số ngẫu nhiên bằng forEach.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

bản đồ

Phương pháp 'bản đồ' được sử dụng để ánh xạ từng phần tử với kết quả tương ứng của nó. Đoạn mã sau đây in các số ô vuông duy nhất bằng bản đồ.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

//get list of unique squares
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

bộ lọc

Phương pháp 'bộ lọc' được sử dụng để loại bỏ các phần tử dựa trên tiêu chí. Đoạn mã sau đây in ra một số chuỗi trống bằng cách sử dụng bộ lọc.

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

//get count of empty string
int count = strings.stream().filter(string -> string.isEmpty()).count();

giới hạn

Phương pháp 'giới hạn' được sử dụng để giảm kích thước của luồng. Đoạn mã sau đây cho thấy cách in 10 số ngẫu nhiên sử dụng giới hạn.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sắp xếp

Phương thức 'đã sắp xếp' được sử dụng để sắp xếp luồng. Đoạn mã sau đây cho thấy cách in 10 số ngẫu nhiên theo thứ tự đã sắp xếp.

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

Tiến trình song song

llelStream là sự thay thế của luồng để xử lý song song. Hãy xem đoạn mã sau in ra số lượng chuỗi trống bằng dòng song song.

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

//get count of empty string
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

Rất dễ dàng chuyển đổi giữa các luồng tuần tự và song song.

Người sưu tầm

Bộ thu thập được sử dụng để kết hợp kết quả xử lý trên các phần tử của một luồng. Bộ sưu tập có thể được sử dụng để trả về một danh sách hoặc một chuỗi.

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

System.out.println("Filtered List: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);

Số liệu thống kê

Với Java 8, bộ thu thập thống kê được giới thiệu để tính toán tất cả các số liệu thống kê khi quá trình xử lý luồng đang được thực hiện.

List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("Highest number in List : " + stats.getMax());
System.out.println("Lowest number in List : " + stats.getMin());
System.out.println("Sum of all numbers : " + stats.getSum());
System.out.println("Average of all numbers : " + stats.getAverage());

Ví dụ về luồng

Tạo chương trình Java sau bằng cách sử dụng bất kỳ trình soạn thảo nào bạn chọn trong C: \> JAVA.

Java8Tester.java

import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;

public class Java8Tester {

   public static void main(String args[]) {
      System.out.println("Using Java 7: ");
		
      // Count empty strings
      List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
      System.out.println("List: " +strings);
      long count = getCountEmptyStringUsingJava7(strings);
		
      System.out.println("Empty Strings: " + count);
      count = getCountLength3UsingJava7(strings);
		
      System.out.println("Strings of length 3: " + count);
		
      //Eliminate empty string
      List<String> filtered = deleteEmptyStringsUsingJava7(strings);
      System.out.println("Filtered List: " + filtered);
		
      //Eliminate empty string and join using comma.
      String mergedString = getMergedStringUsingJava7(strings,", ");
      System.out.println("Merged String: " + mergedString);
      List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
		
      //get list of square of distinct numbers
      List<Integer> squaresList = getSquares(numbers);
      System.out.println("Squares List: " + squaresList);
      List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
		
      System.out.println("List: " +integers);
      System.out.println("Highest number in List : " + getMax(integers));
      System.out.println("Lowest number in List : " + getMin(integers));
      System.out.println("Sum of all numbers : " + getSum(integers));
      System.out.println("Average of all numbers : " + getAverage(integers));
      System.out.println("Random Numbers: ");
		
      //print ten random numbers
      Random random = new Random();
		
      for(int i = 0; i < 10; i++) {
         System.out.println(random.nextInt());
      }
		
      System.out.println("Using Java 8: ");
      System.out.println("List: " +strings);
		
      count = strings.stream().filter(string->string.isEmpty()).count();
      System.out.println("Empty Strings: " + count);
		
      count = strings.stream().filter(string -> string.length() == 3).count();
      System.out.println("Strings of length 3: " + count);
		
      filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList());
      System.out.println("Filtered List: " + filtered);
		
      mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", "));
      System.out.println("Merged String: " + mergedString);
		
      squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
      System.out.println("Squares List: " + squaresList);
      System.out.println("List: " +integers);
		
      IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();
		
      System.out.println("Highest number in List : " + stats.getMax());
      System.out.println("Lowest number in List : " + stats.getMin());
      System.out.println("Sum of all numbers : " + stats.getSum());
      System.out.println("Average of all numbers : " + stats.getAverage());
      System.out.println("Random Numbers: ");
		
      random.ints().limit(10).sorted().forEach(System.out::println);
		
      //parallel processing
      count = strings.parallelStream().filter(string -> string.isEmpty()).count();
      System.out.println("Empty Strings: " + count);
   }
	
   private static int getCountEmptyStringUsingJava7(List<String> strings) {
      int count = 0;

      for(String string: strings) {
		
         if(string.isEmpty()) {
            count++;
         }
      }
      return count;
   }
	
   private static int getCountLength3UsingJava7(List<String> strings) {
      int count = 0;
		
      for(String string: strings) {
		
         if(string.length() == 3) {
            count++;
         }
      }
      return count;
   }
	
   private static List<String> deleteEmptyStringsUsingJava7(List<String> strings) {
      List<String> filteredList = new ArrayList<String>();
		
      for(String string: strings) {
		
         if(!string.isEmpty()) {
             filteredList.add(string);
         }
      }
      return filteredList;
   }
	
   private static String getMergedStringUsingJava7(List<String> strings, String separator) {
      StringBuilder stringBuilder = new StringBuilder();
		
      for(String string: strings) {
		
         if(!string.isEmpty()) {
            stringBuilder.append(string);
            stringBuilder.append(separator);
         }
      }
      String mergedString = stringBuilder.toString();
      return mergedString.substring(0, mergedString.length()-2);
   }
	
   private static List<Integer> getSquares(List<Integer> numbers) {
      List<Integer> squaresList = new ArrayList<Integer>();
		
      for(Integer number: numbers) {
         Integer square = new Integer(number.intValue() * number.intValue());
			
         if(!squaresList.contains(square)) {
            squaresList.add(square);
         }
      }
      return squaresList;
   }
	
   private static int getMax(List<Integer> numbers) {
      int max = numbers.get(0);
		
      for(int i = 1;i < numbers.size();i++) {
		
         Integer number = numbers.get(i);
			
         if(number.intValue() > max) {
            max = number.intValue();
         }
      }
      return max;
   }
	
   private static int getMin(List<Integer> numbers) {
      int min = numbers.get(0);
		
      for(int i= 1;i < numbers.size();i++) {
         Integer number = numbers.get(i);
		
         if(number.intValue() < min) {
            min = number.intValue();
         }
      }
      return min;
   }
	
   private static int getSum(List numbers) {
      int sum = (int)(numbers.get(0));
		
      for(int i = 1;i < numbers.size();i++) {
         sum += (int)numbers.get(i);
      }
      return sum;
   }
	
   private static int getAverage(List<Integer> numbers) {
      return getSum(numbers) / numbers.size();
   }
}

Xác minh kết quả

Biên dịch lớp bằng cách sử dụng javac trình biên dịch như sau -

C:\JAVA>javac Java8Tester.java

Bây giờ chạy Java8Tester như sau:

C:\JAVA>java Java8Tester

Nó sẽ tạo ra kết quả sau:

Using Java 7:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9
Random Numbers:
-1279735475
903418352
-1133928044
-1571118911
628530462
18407523
-881538250
-718932165
270259229
421676854
Using Java 8:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9.444444444444445
Random Numbers:
-1009474951
-551240647
-2484714
181614550
933444268
1227850416
1579250773
1627454872
1683033687
1798939493
Empty Strings: 2