STDIO
Tìm kiếm gần đây
    Nội dung
    0
    0
    Chia sẻ
    Nội dung
    0
    0
    Chia sẻ

    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 10/11/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.

    0 Bình luận
    Java

    Java

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

    Khi bạn nhấn vào sản phẩm do chúng tôi đề xuất và mua hàng, chúng tôi sẽ nhận được hoa hồng. Điều này hỗ trợ chúng tôi có thêm kinh phí tạo nhiều nội dung hữu ích. Tìm hiểu thêm.
    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 - 2021