Java - Lọc luồng bằng biểu thức Lambda PlatoBlockchain Data Intelligence. Tìm kiếm dọc. Ái.

Java - Lọc Luồng với Biểu thức Lambda

Java Streams đã được giới thiệu trong Java 8 vào năm 2014, với nỗ lực giới thiệu Java dài dòng vào một mô hình Lập trình Chức năng. Java Streams thể hiện nhiều hoạt động chức năng linh hoạt và mạnh mẽ để thực hiện xử lý thu thập trong một lớp.

Lọc bộ sưu tập dựa trên một số vị từ vẫn là một trong những hoạt động chức năng được sử dụng phổ biến nhất và có thể được thực hiện với Predicate hoặc chính xác hơn – với một Biểu thức Lambda.

Trong hướng dẫn ngắn này, chúng ta sẽ xem cách bạn có thể lọc Luồng Java 8 bằng Biểu thức Lambda.

Lọc các luồng trong Java

Nói chung, bất kỳ Stream có thể được lọc qua filter() phương thức và một vị từ đã cho:

Stream filter(Predicate<? super T> predicate)

Mỗi phần tử trong luồng được chạy đối với vị từ và được thêm vào luồng đầu ra nếu vị từ trả về true. Bạn có thể cung cấp một Predicate ví dụ:

Predicate contains = s -> s.contains("_deprecated");
List results = stream.filter(contains).collect(Collectors.toList());

Hoặc, đơn giản hóa nó bằng cách cung cấp Biểu thức Lambda:

List results = stream.filter(s -> s.contains("_deprecated"))
                             .collect(Collectors.toList());

Hoặc thậm chí thu gọn Biểu thức Lambda thành tham chiếu phương pháp:


List results = stream.filter(String::isEmpty)
                             .collect(Collectors.toList());

Tuy nhiên, với tham chiếu phương thức, bạn không thể truyền đối số, bạn có thể xác định các phương thức trong đối tượng bạn đang lọc và điều chỉnh chúng để có thể dễ dàng lọc được (miễn là phương thức đó không chấp nhận đối số và trả về một giá trị tham chiếu phương thức). boolean).

Hãy nhớ rằng luồng không phải là bộ sưu tập – chúng là những luồng trong số các bộ sưu tậpvà bạn sẽ phải thu thập chúng lại vào bất kỳ bộ sưu tập nào chẳng hạn như List, Map, v.v. để mang lại cho chúng tính lâu dài. Ngoài ra, tất cả các hoạt động được thực hiện trên các phần tử luồng trung gian or thiết bị đầu cuối:

  • Các hoạt động trung gian trả về một luồng mới với các thay đổi so với hoạt động trước đó
  • Các hoạt động đầu cuối trả về một kiểu dữ liệu và có nghĩa là để kết thúc quá trình xử lý trên một luồng

filter() là một trung gian hoạt động và được kết nối với các hoạt động trung gian khác trước khi luồng kết thúc. Để duy trì bất kỳ thay đổi nào (chẳng hạn như thay đổi chính các thành phần hoặc kết quả được lọc), bạn sẽ phải chỉ định kết quả dòng đầu ra đến một biến tham chiếu mới, thông qua một hoạt động đầu cuối.

Lưu ý: Ngay cả khi xâu chuỗi nhiều biểu thức lambda, bạn có thể không gặp phải các vấn đề về khả năng đọc, với dấu ngắt dòng thích hợp.

Trong các ví dụ sau, chúng ta sẽ làm việc với danh sách sách này:

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
        
List books = Arrays.asList(book1, book2, book3);

Lọc Bộ sưu tập với Stream.filter ()

Hãy lọc bộ sưu tập sách này. Bất kỳ vị từ nào cũng được - vì vậy, ví dụ, hãy lọc theo những cuốn sách có trên 400 trang:

List results = books.stream()
                          .filter(b -> b.getPageNumber() > 400)
                          .collect(Collectors.toList());

Điều này dẫn đến một danh sách bao gồm:

[
Book{id='001', name='Our Mathematical Universe', author='Max Tegmark', pageNumber=432, publishedYear=2014}, 
Book{id='003', name='Sapiens', author='Yuval Noah Harari', pageNumber=443, publishedYear=2011}
]

Khi lọc, một phương pháp thực sự hữu ích để xâu chuỗi là map(), cho phép bạn ánh xạ các đối tượng sang một giá trị khác. Ví dụ: chúng tôi có thể ánh xạ từng cuốn sách với tên của nó và do đó chỉ trả về tên trong số những cuốn sách phù hợp với vị ngữ từ filter() gọi:

List results = books.stream()
                            .filter(b -> b.getPageNumber() > 400)
                            .map(Book::getName)
                            .collect(Collectors.toList());

Điều này dẫn đến một danh sách các chuỗi:

[Our Mathematical Universe, Sapiens]

Lọc Bộ sưu tập trên Nhiều Dự đoán với Stream.filter ()

Thông thường, chúng tôi muốn lọc các bộ sưu tập theo nhiều tiêu chí. Điều này có thể được thực hiện bằng cách xâu chuỗi nhiều filter() cuộc gọi or sử dụng một vị từ ngắn mạch, có hai điều kiện trong một filter() gọi.

 List results = books.stream()
                    .filter(b -> b.getPageNumber() > 400 && b.getName().length() > 10)
                    .collect(Collectors.toList());
                    


 List results2 = books.stream()
                    .filter(b -> b.getPageNumber() > 400)
                    .filter(b -> b.getName().length() > 10)
                    .collect(Collectors.toList());

Xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, các tiêu chuẩn được ngành công nghiệp chấp nhận và bảng lừa đảo đi kèm. Dừng lệnh Googling Git và thực sự học nó!

Khi sử dụng nhiều tiêu chí – lệnh gọi lambda có thể hơi dài. Tại thời điểm này, việc trích xuất chúng dưới dạng các vị từ độc lập có thể mang lại sự rõ ràng hơn. Tuy nhiên, cách tiếp cận nào nhanh hơn?

Bộ lọc đơn với điều kiện phức tạp hay nhiều bộ lọc?

Nó phụ thuộc vào phần cứng của bạn, bộ sưu tập của bạn lớn đến mức nào và liệu bạn có sử dụng các luồng song song hay không. Nói chung – một bộ lọc có điều kiện phức tạp sẽ hoạt động tốt hơn nhiều bộ lọc có điều kiện đơn giản hơn (bộ sưu tập từ nhỏ đến trung bình) hoặc hoạt động ở cùng cấp độ (bộ sưu tập rất lớn). Nếu điều kiện của bạn quá dài – bạn có thể hưởng lợi từ việc phân phối chúng qua nhiều filter() cuộc gọi, để cải thiện khả năng đọc, vì hiệu suất rất giống nhau.

Sự lựa chọn tốt nhất là thử cả hai, lưu ý hiệu suất trên Thiết bị mục tiêuvà điều chỉnh chiến lược của bạn cho phù hợp.

Người dùng GitHub volkodav đã thực hiện một tiêu chuẩn lọc trong / s hoạt động thông lượng và lưu trữ kết quả trên “javafilters-điểm chuẩn” kho. Kết quả được tóm tắt trong một bảng thông tin:

Nó cho thấy lợi nhuận giảm dần rõ ràng ở quy mô bộ sưu tập lớn hơn, với cả hai phương pháp đều hoạt động ở cùng mức độ. Các luồng song song được hưởng lợi đáng kể ở kích thước bộ sưu tập lớn hơn, nhưng hạn chế hiệu suất ở kích thước nhỏ hơn (dưới ~10k phần tử). Điều đáng chú ý là các luồng song song duy trì thông lượng của chúng tốt hơn nhiều so với các luồng không song song, khiến chúng trở nên mạnh mẽ hơn đáng kể khi nhập dữ liệu.

Dấu thời gian:

Thêm từ xếp chồng lên nhau