STDIO
Tìm kiếm gần đây
    • 0

    Các Operations Hữu Ích của Stream<T>

    Các operations thường dùng của Stream<T> trong Java: Intermediate operations và Terminal operations.
    15/01/2015
    19/09/2020
    5 phút đọc
    Các Operations Hữu Ích của Stream<T>

    Giới thiệu và cách sử dụng các operations hữu ích thường được sử dụng với Stream<T> trong Java.

    Để dễ hiểu, Stream đơn thuần dùng để xử lý các vấn đề thường gặp ở danh sách như.

    • Duyệt danh sách.
    • Lọc bớt phần tử trong danh sách theo các tiêu chí.
    • Thêm hoặc cắt gọt các thuộc tính của các phần tử trong danh sách.
    • Sắp xếp danh sách.
    • ...

    *Có thể nói, C# có LinQ thì Java có Stream.

    Pipeline

    Khi sử dụng Stream, bạn sẽ biết thêm về khái niệm Pipeline; có thể hiểu là 1 đường ống mà dòng chảy sẽ đi qua, trên đường ống này, có các operation (trong lập trình đơn thuần là các phương thức) sẽ làm thay đổi dòng chảy đó.

    Operation có thể hiểu là các "đốt" mà ở đó dòng chảy sẽ thay đổi tính chất, có 2 loại operation là intermediate (đốt trên đường đi) và terminal (đốt cuối cùng).

    Ví dụ có 1 danh sách tài khoản vừa truy vấn từ cơ sở dữ liệu và cần các thao tác sau trước khi trả về cho Frontend.

    • Cắt gọt các thuộc tính password, hoặc các thông tin bảo mật trong tất cả tài khoản - dùng map operation.
    • Tiếp tục lọc bớt tất cả tài khoản đã tạo trước năm 1990 - dùng filter operation.
    • Tiếp tục thêm 1 thuộc tính là fullName vào tất cả tài khoản bằng cách nối firstNamelastName trong tài khoản - dùng map operation.
    Stream pipeline
    Dòng chảy (stream) trong pipeline

    Phân loại operation

    Có 2 loại operation:

    • Intermediate operations: là các operations sau khi vận hành sẽ trả về 1 stream khác (lúc này dòng chảy vẫn chưa kết thúc).
    • Terminal operations: là các operations sau khi vận hành sẽ không trả về 1 stream mà có thể là mảng, collections, giá trị hoặc không trả về kết quả (void) (dòng chảy kết thúc tại đây để đưa ra kết quả cuối cùng có thể dùng được).

    Các intermediate operations thường được đặt trước terminal operation và chúng sẽ không được thực thi cho đến khi có terminal operation.

    Các Intermediate operations

    filter

    Phương thức dùng để lọc ra tất cả những phần tử trong stream có giá trị thỏa với điều kiện.

    Collection<String> collection = Arrays.asList("aa" , "ba", "aa", "abb");
    Stream<String> streamOfCollection = collection.stream();
    
    streamOfCollection.filter(x -> x.startsWith("a"))
                      .forEach(x -> System.out.println(x + "; "));
    
    //aa; aa; abb; 
    

    map

    Map giá trị của từng phần tử trong Stream vào một function mà chúng ta truyền vào và trả về giá trị mới.

    Stream<String> streamOfArray = Stream.of("aa", "aa", "abb");
    
    streamOfArray.map(x -> x + "c")
                 .forEach(x -> System.out.print(x + "; "));
    
    //aac; bac; aac; abbc;
    

    flatmap

    Biến đổi mỗi phần tử trong Stream (thường là những phần tử phức tạp như List, Set, Array) thành những phần tử đơn giản hơn.

    List<Integer> s1 = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> s2 = Arrays.asList(6, 7, 8, 9, 10);
    		
    List<List<Integer>> s = Arrays.asList(s1, s2);
    
    Stream<List<Integer>> stream = s.stream();
    stream.flatMap(a -> a.stream())
    		   .forEach(x -> System.out.print(x + "; "));
    
    //1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 

    distinct

    Loại bỏ các phần tử trùng nhau trong Stream và trả về 1 Stream với các phần tử riêng biệt.

    Stream<String> streamOfArray = Stream.of("aa", "ba", "aa", "abb");
            
    streamOfArray.distinct()
                 .forEach(x -> System.out.print(x + "; "));
    
    //aa; ba; abb;
    

    sorted

    Trả về một Stream mà các phần tử đã được sắp xếp theo thứ tự.

    Stream<String> streamOfArray = Stream.of("aa", "ba", "aa", "abb");
            
    streamOfArray.sorted((a,b)->a.compareTo(b))
                 .forEach(x -> System.out.print(x + "; "));
    
    //aa; aa; abb; ba;
    

    limit

    Giới hạn số lượng phần tử tối đa trong Stream.

    Stream<String> streamOfArray = Stream.of("aa", "ba", "aa", "abb");
            
    streamOfArray.limit(3)
                 .forEach(x -> System.out.print(x + "; "));
    
    //aa; ba; aa; 
    

    peek

    Gần giống như forEach, peek cho phép duyệt qua tất cả các phần tử trong Stream và thực hiện các tính toán trên các phần tử đó đồng thời trả về 1 Stream.

    Stream<Integer> streamOfArray = Stream.of(1, 2, 3, 4);
                   
    System.out.print("The number divisible by two is: ");
    long count = streamOfArray.peek(x -> {if (x % 2 == 0) System.out.print(x + "; ");})
                              .count();
        
    //The number divisible by two is: 2; 4; 
    

    Các Terminal operations

    forEach

    Phương thức cho phép duyệt qua tất cả các phần từ trong Stream và thực hiện các tính toán từ các giá trị đó.

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

    collect

    Phương thức dùng để convert một Stream thành một List, Set, Map.

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

    toArray()

    Convert 1 Stream sang Array.

    Stream<Integer> intStream = Stream.of(1,2,3,4);
    
    Integer[] intArray = intStream.toArray(Integer[]::new);
    
    System.out.println(Arrays.toString(intArray)); 
    
    //[1, 2, 3, 4]

    count

    Trả về số lượng phần tử của stream sau khi thực hiện filter.

    Stream<Integer> streamOfArray = Stream.of(1, 2, 3, 4);
    
    long count = streamOfArray.count();
    
    System.out.println("Number of elements in the array is: " + count);
    
    Number of elements in the array is: 4
    

    min

    Trả về giá trị nhỏ nhất của Stream.

    Stream.of(1, 5, 4)
          .min()
          .ifPresent(System.out::println); 
    
    //1

    max

    Trả về giá trị lớn nhất của Stream.

    Stream.of(1, 5, 4)
          .max()
          .ifPresent(System.out::println); 
    
    //5

    reduce

    Giúp làm giảm các phần tử của stream về một giá trị.

    Stream<Integer> streamOfArray = Stream.of(1, 2 , 3, 4);
            
    Integer result  = streamOfArray.reduce((a, b) -> a + b)
                                   .get();
    
    System.out.print(result);
    
    //10

    Vì sao sử dụng Stream?

    Stream cũng chỉ là 1 cách tiếp cận, 1 phương pháp code trong lập trình với Java và các danh sách. Tuy nhiên, nó tiện lợi, như những code mẫu về các operations trên, bạn không cần thiết phải for (int i = 0; i < accounts.length(); i++) mọi lúc mọi nơi và thực tế của các trường hợp ứng dụng, vòng lặp for biến i hay accounts.length() cũng không đóng góp vai trò gì ngoài việc kiểm soát chỉ số, số lần lặp nhưng lại chiếm dụng thời gian code, sự quan tâm và làm cho code dài hơn.

    Java

    Java

    Tổng hợp các bài viết Java hữu ích

    Sản phẩm

    Đề xuất

    Vector Trong Unity

    Vector Trong Unity

    Giới thiệu và hướng dẫn sử dụng các đối tượng cơ bản thuộc lớp Vector3 ...

    Lập Trình GameUnity

    08/08/2015

    Thỏa Thuận Sử Dụng Dịch Vụ STDIO

    Thỏa Thuận Sử Dụng Dịch Vụ STDIO

    Thỏa thuận này quy định về điều kiện giao kết hợp đồng, quyền lợi, nghĩa ...

    STDIOChính sách

    07/04/2014

    Khám phá thêm

    Quản Lý Vị Trí Các Đối Tượng Trong Game

    Quản Lý Vị Trí Các Đối Tượng Trong Game

    Thông thường khi khởi tạo một đối tượng trong game, các lập trình viên ...

    Lập Trình GameKiến Thức Nâng Cao

    30/03/2015

    Rvalue References và Move Semantics

    Rvalue References và Move Semantics

    Khái niệm rvalue reference, và ứng dụng để định nghĩa "move semantic" ...

    Modern C++C++0x

    02/12/2014

    Box2D - Phần 3: Joint

    Box2D - Phần 3: Joint

    Tiếp tục chuỗi bài viết giới thiệu về Box2D. Bài viết giới ...

    Lập Trình GameKiến Thức Nâng Cao

    23/01/2015

    Bí Mật Của SEO - Phần 3

    Bí Mật Của SEO - Phần 3

    Tìm hiểu việc tối ưu hóa trải nghiệm người dùng từ hình ảnh, nội dung ...

    STDIO SolutionsSEO

    11/07/2020

    Ba Định Luật Cơ Bản của Dòng Điện

    Ba Định Luật Cơ Bản của Dòng Điện

    Trong các mạch điện luôn tồn tại các định luật cơ bản của dòng và thế ở ...

    Điện Tử Ứng DụngKiến thức & linh kiện

    01/06/2017

    10 Phần Mềm Nổi Tiếng Được Viết Bằng C/C++

    10 Phần Mềm Nổi Tiếng Được Viết Bằng C/C++

    Giới thiệu các phần mềm nổi tiếng được viết bằng C/C++ với hiệu năng ...

    STDIO TrainingGóc nhìn

    09/08/2020

    Lập Trình Win32 API - Phần 2: Tạo Cửa Sổ Cơ Bản

    Lập Trình Win32 API - Phần 2: Tạo Cửa Sổ Cơ Bản

    Hệ điều hành Windows cung cấp các cửa sổ Window. Có thể sử dụng Win32 ...

    Modern C++Win32 API

    12/09/2015

    STDIO
    Trang chính
    Công ty TNHH STDIO

    30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
    +84 28.36205514 - +84 942.111912
    developer@stdio.vn

    383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
    Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012

    ©STDIO, 2013 - 2020