JavaRush /Blog Java /Random-VI /Luồng đơn giản không đơn giản
Oleg Savenko
Mức độ
Одесса

Luồng đơn giản không đơn giản

Xuất bản trong nhóm
Với mỗi phiên bản Java mới, nó ngày càng trở nên phong phú hơn. Mặc dù phần lớn sự phong phú nằm ở các phiên bản trước đó nhưng ngôn ngữ này vẫn tiếp tục được cải thiện cả về phương pháp và cách thực hiện. Các bộ sưu tập trong Java cũng không ngoại lệ. Khung bộ sưu tập cốt lõi đã xuất hiện trong J2SE 1.2 và tiếp tục phát triển, trải qua những thay đổi khiến bạn hài lòng hơn là thất vọng. Với việc phát hành JDK 5, các bộ sưu tập đã trở nên thuận tiện hơn, nhanh hơn và dễ làm việc hơn. Điều này dẫn đến việc các lập trình viên bắt đầu khai thác chúng một cách mạnh mẽ hơn. Một số mẫu nhất định đã được phát triển để làm việc với chúng, chắc chắn là có hiệu quả. Nhưng với JDK 8, các bộ sưu tập đã trở nên tốt hơn trở lại và chúng trở nên tốt hơn nhờ các luồng. Rõ ràng, do bộ sưu tập có thể được biểu diễn dưới dạng luồng nên phương pháp làm việc với chúng cũng sẽ thay đổi. Vì vậy, tôi muốn cho thấy các giải pháp quen thuộc và dễ hiểu với các bộ sưu tập càng trở nên đơn giản hơn như thế nào.

Ví dụ 1. Không thể đơn giản hơn

Tất nhiên, hãy bắt đầu với điều đơn giản nhất, hãy xem qua tất cả các phần tử của bộ sưu tập và hiển thị tất cả các phần tử.
// создадим и заполним список
   List<Integer> list = new ArrayList<>();
   Collections.addAll(list, 1, 5, 6, 11, 3, 15, 7, 8);
   // а теперь
   // быстрый for по всем elementм, только для коллекций
   for (Integer i:list){
       System.out.println(i);
   }
   //но мы уже живем в JDK 8
   //а значит нужно так
   list.stream().forEach(System.out::println);
Như bạn đã nhận thấy, có một cú pháp mới, theo tôi, với tư cách là người mới sử dụng Java, đơn giản hơn nhiều. Vì vậy, những gì hiển thị trong cú pháp mới:
берем_список(list).превращаем_в_поток(stream).перебираем_все_элементы(forEach)(тут_интуитивно_понятно)
System.out::println— một liên kết đến một phương thức tĩnh xuất ra một chuỗi tới bảng điều khiển. Thay vì liên kết đến một phương thức tĩnh, bạn có thể sử dụng một mục nhập hơi khác, ít rõ ràng hơn:
list.stream().forEach(i -> System.out.println(i));
Mục này sử dụng biểu thức lambda. Và vâng, để học cách làm việc với luồng, bạn sẽ cần học các biểu thức lambda - chúng thật tuyệt vời. Hơn nữa, tôi sẽ không chỉ ra cách làm việc với các bộ sưu tập chỉ sử dụng các luồng, dựa trên thực tế là bạn đã quen với các phương pháp truyền thống trong suốt khóa học.

Ví dụ 2. Tìm các giá trị chẵn trong danh sách và hiển thị chúng trong bảng điều khiển

list.stream().filter(i -> i%2==0).forEach(System.out::println);
Toàn bộ vấn đề đã được giải quyết trong một dòng. Tôi hy vọng bạn thích làm việc trong một dòng. Bằng cách sử dụng phương pháp này, filterchúng tôi đã lọc luồng và xuất những gì còn lại vào bảng điều khiển. Bộ lọc là một thứ rất mạnh mẽ có thể giúp ích trong những trường hợp bất ngờ nhất. Hãy sáng tạo và thay đổi các điều kiện của vấn đề. Ví dụ: chúng ta cần đếm xem có bao nhiêu số chẵn trong danh sách:
long count = list.stream().filter(i -> i%2==0).count();
Và một lần nữa trong một dòng. Bằng cách nào đó mọi thứ có vẻ đơn giản. Trong bộ lọc, chúng tôi đã sử dụng biểu thức lambda, do đó chỉ đặt các số chẵn trong luồng mới, sau đó áp dụng cho luồng mới để countđếm xem có bao nhiêu phần tử trong luồng mới.

Ví dụ 3. Đếm xem có bao nhiêu từ trong danh sách dài 5 ký tự

Chúng ta đã chơi với số nguyên, bây giờ hãy chơi với từ.
List<String> list = new ArrayList<>();
Collections.addAll(list, "разые", "слова", "интересные", "And", "Not", "Very");

System.out.println(list.stream().filter(w -> w.length() == 5).count());
Chúng tôi đã sử dụng lại bộ lọc. Trong bộ lọc, sử dụng biểu thức lambda, một luồng mới được hiển thị và sau đó, có thể hiểu được, counttôi đã tính toán xem có bao nhiêu phần tử trong luồng mới.

Ví dụ 4. In chữ duy nhất

Một công việc quen thuộc khi chúng ta đọc nhiều từ khác nhau vào một tập hợp từ một tệp và bây giờ chúng ta chỉ cần những từ duy nhất.
List<String> list = new ArrayList<>();
Collections.addAll(list, "Vasya", "Таня", "Olya", "Vasya", "Olya", "Сергей");

list.stream().distinct().forEach(System.out::println);
Hành động chính được thực hiện trên luồng bằng cách sử dụng distinct. Tiếp theo, tôi khuyên bạn nên xem qua một số nhiệm vụ của chúng ta trong khóa học bằng cách sử dụng các chuỗi

Ví dụ 5. Từ dài

Ở cấp độ 9 của Java Core, trong bài giảng 11 có một vấn đề thú vị, trong đó bạn cần viết các từ cách nhau bằng dấu phẩy trong File2, độ dài của nó lớn hơn 6. Cho dù bạn đang làm hàng rào cho loại vườn nào, Tôi đề xuất giải pháp sau:
  1. Từ file nguồn chúng ta đọc tất cả các từ trong danh sách.

  2. Sau đó chúng ta thực hiện dòng sau

    Optional<String> rezult = list.stream()
    				.filter(w->w.length()>6)
    				.reduce((w1,w2)->w1+", "+w2);
  3. result.get()ghi vào một tập tin.

Đây là một giải pháp thú vị bằng cách sử dụng chủ đề. Bộ lọc được lọc và sử dụng biểu thức rút gọn và biểu thức chính quy, chuỗi bắt buộc đã được tạo.

Ví dụ 6. Từ có số

Viết tất cả các từ có chứa số, ví dụ: a1 hoặc abc3d, cách nhau bằng dấu cách trong File2. Đây cũng là một điều kiện trong sách bài tập của chúng tôi, như bạn đoán, giải pháp rất đơn giản.
Optional<String> rezult = list.stream()
				.filter(w->w.matches(".*?\\d+.*?"))
				.reduce((w1,w2)->w1+" "+w2);
Chúng tôi đã lọc luồng bằng cách sử dụng biểu thức chính quy, sau đó rút gọn và biểu thức lambda. Rất nhiều điểm chung với nhiệm vụ trước đó.

Ví dụ 7. Chọn số

Toàn bộ nhiệm vụ nghe như thế này:
  • Đọc 2 tên tệp từ bảng điều khiển.
  • Xuất ra tệp thứ hai tất cả các số có trong tệp đầu tiên.
  • Các số được phân tách bằng dấu cách.
  • Đóng luồng.
Đối với tác vụ chính là ghi các số vào một chuỗi cách nhau bằng dấu cách, để ghi tiếp vào tệp, tôi khuyên bạn nên sử dụng luồng, nó sẽ trông như thế này:
Optional<String> rezult = list.stream().filter(w->w.matches("\\d+"))
				.reduce((w1,w2)->w1+" "+w2);
System.out.println(rezult.get());
Sử dụng các luồng, vấn đề được giải quyết một cách rất đơn giản. Tuy nhiên, hãy xem, hãy tự mình so sánh giải pháp này với hai giải pháp trước đó. Kết thúc bài viết, tôi muốn thú nhận với các bạn: các bạn ơi, tôi đã gian lận khi chọn ví dụ. Thực tế là tôi đã chọn những ví dụ đơn giản nhất để cho bạn thấy một chủ đề xa lạ bằng cách sử dụng các vấn đề quen thuộc. Tất nhiên, các luồng được sử dụng cho cả các tác vụ đơn giản và phức tạp hơn. Nhưng như Horstman đã nhấn mạnh trong cuốn sách của mình, “Các luồng dữ liệu hoạt động theo nguyên tắc “làm gì chứ không phải làm như thế nào”. Điều đó có nghĩa là nhiều nhiệm vụ phức tạp trước đây có thể trở nên đơn giản hơn. Không biết bạn thế nào, nhưng tôi thích các dòng chảy, tôi hy vọng tôi không ngăn cản bạn học chúng. Và hãy để tôi giải thích thêm một điều nữa:
  1. Tôi không có ý định dạy người đọc cách sử dụng các luồng trong bộ sưu tập; tôi không phải là một giáo viên có kinh nghiệm. Tôi muốn cho bạn thấy rằng các chủ đề rất đơn giản và rất thú vị! Nói chung đây là điều cần thiết.
  2. Càng hiểu về các dòng, tôi càng thấy những vấn đề mà chúng giải quyết được tất cả các bài toán trong sách giáo khoa, điều đó có nghĩa là các dòng đó không được phát minh ra một cách vô ích.
  3. Các luồng không chỉ dễ làm việc mà còn có một lợi thế quan trọng - khi làm việc với lượng lớn dữ liệu, các luồng thường hiệu quả hơn.
Tái bút . Tôi đã nói đùa về TẤT CẢ CÁC VẤN ĐỀ. Đề xuất: Thư viện Java chuyên nghiệp. Tập 2 Công cụ lập trình nâng cao. Kay Horstmann. Tôi có ấn bản thứ mười.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION