12 cách phổ biến để sử dụng luồng Java
Nguồn: Dev.to API Java Streams xuất hiện lần đầu tiên trong Java 8. Mục đích của nó là cung cấp một cách nhỏ gọn hơn để thực hiện các thao tác phổ biến trên các bộ sưu tập đối tượng. Ngoài ra, API Java Streams có thể được sử dụng để triển khai các thuật toán phức tạp. Trong bài viết này, chúng ta sẽ nói về các trường hợp sử dụng phổ biến của Luồng Java. Trước tiên, hãy làm rõ một số điều cơ bản:-
luồng() - tạo luồng từ bộ sưu tập.
-
coll() - thu thập luồng vào một đối tượng. Một đối tượng có thể là một bộ sưu tập, một lớp nguyên thủy hoặc một lớp tùy chỉnh.
-
Collectors là lớp cung cấp (nhiều) phương thức tĩnh để thu thập luồng.
1. Lọc
-
Được sử dụng để xóa các giá trị khỏi Bộ sưu tập dựa trên một điều kiện.
-
Để lọc các phần tử của bộ sưu tập dựa trên một điều kiện, hãy sử dụng phương thức filter() . Chỉ các phần tử phù hợp mới được lưu.
List<Integer> evenNumbers = originalList.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
2. Tiền xử lý
-
Hữu ích khi mọi giá trị trong bộ sưu tập cần được thay đổi tại chỗ.
-
Phương thức map() được sử dụng để áp dụng một hàm cho từng phần tử của bộ sưu tập và trả về một tập hợp các giá trị được tính toán mới.
List<Integer> squares = originalList.stream()
.map(n -> n * n)
.collect(Collectors.toList());
3. Chuyển đổi
-
Hữu ích khi chúng ta muốn chuyển đổi một bộ sưu tập thành một bộ sưu tập khác.
-
Có một số cách để đạt được điều này.
Ví dụ 1: Tạo Bản đồ từ Danh sách.
Chuyển đổi danh sách các chuỗi thành bản đồ các chuỗi và độ dài.Map<String, Integer> wordLengths = words.stream()
.collect(Collectors.toMap(
word -> word,
word -> word.length()));
Ví dụ 2. Chuyển đổi danh sách thành tập hợp.
Đây là trường hợp sử dụng phổ biến để loại bỏ các bản sao. Ngoài ra, nếu muốn đưa các phần tử trở lại danh sách, chúng ta có thể sử dụng các phương thức stream() và coll() hai lần . Ví dụ: hãy chuyển đổi danh sách các chuỗi thành danh sách các chuỗi duy nhất:// if we want to collect to a set
Set<String> uniqueWords = words.stream()
.collect(Collectors.toSet());
// OR
// if we want to start and end as a list
List<String> uniqueWords = words.stream()
.collect(Collectors.toSet()).stream().collect(Collectors.toList());
Ví dụ 3. Chuyển đổi danh sách sản phẩm thành danh sách tên của chúng. (Làm phẳng - Căn chỉnh)
List<String> productNames = products.stream()
.map(product -> product.getName())
.collect(Collectors.toList());
4. Giảm
-
Giảm Bộ sưu tập thành một giá trị duy nhất.
-
Phương thức less() được sử dụng để áp dụng một hàm cho từng phần tử của bộ sưu tập và trả về một giá trị duy nhất.
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
5. Phân nhóm
-
Nhóm các thành phần của Bộ sưu tập dựa trên một điều kiện nhất định.
-
Để nhóm các thành phần của Bộ sưu tập theo điều kiện, hãy sử dụng phương thức Collectors.groupingBy() .
Map<String, List<Product>> productsByCategory = products.stream()
.collect(Collectors.groupingBy(product -> product.getCategory()));
6. Tìm kiếm
-
Tìm kiếm phần tử Bộ sưu tập đầu tiên hoặc bất kỳ phần tử nào khớp với một điều kiện.
-
Các phương thức findFirst() và findAny() được sử dụng để tìm kiếm .
Optional<String> firstLongWord = words.stream()
.filter(word -> word.length() > 5)
.findFirst();
// Note that findFirst() and findAny() methods return Optional<T> objects.
7. Sắp xếp
-
Sắp xếp các thành phần của Bộ sưu tập.
-
Phương thức được sắp xếp () được sử dụng để sắp xếp .
List<Integer> topK = numbers.stream()
.sorted()
.limit(k)
.collect(Collectors.toList());
8. Phân vùng
-
Phân tách các thành phần của Bộ sưu tập dựa trên một điều kiện nhất định.
-
Phương thức Collectors.partitioningBy() được sử dụng để phân tách các phần tử .
Map<Boolean, List<Student>> passingFailing = students
.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
9. Đếm
-
Đếm số phần tử thoả mãn điều kiện.
-
Phương thức count() được sử dụng để đếm số phần tử thỏa mãn một điều kiện .
long count = words.stream()
.filter(word -> word.length() > 5)
.count();
10. Phạm vi
-
Tạo ra một loạt các giá trị.
-
Để tạo một phạm vi giá trị, hãy sử dụng phương thức range() .
int[] numbers = IntStream.range(0, 10).toArray();
11. Kết hợp
-
Khớp các phần tử của một tập hợp với một vị từ (điều kiện).
-
Các phương thức như AnyMatch() , allMatch() và noneMatch() được sử dụng để khớp các phần tử bộ sưu tập với một vị từ và trả về giá trị boolean .
// true when all elements match the predicate
boolean allMatch = products.stream()
.allMatch(product -> product.getPrice() > 10);
// true when any element matches the predicate
boolean anyMatch = products.stream()
.anyMatch(product -> product.getPrice() > 10);
// true when no elements match the predicate
boolean noneMatch = products.stream()
.noneMatch(product -> product.getPrice() > 10);
12. Tham gia
-
Nối các phần tử của tập hợp thành một chuỗi.
-
Để nối các phần tử của bộ sưu tập thành một chuỗi, hãy sử dụng phương thức Collectors.joining() .
String joinedWords = words.stream()
.collect(Collectors.joining(" "));
Đó là cho các kịch bản chung. Có những tình huống khác ít phổ biến hơn mà bạn có thể tự mình khám phá:
- Luồng song song;
- Số liệu thống kê;
- Nhà sưu tập tùy chỉnh.
Lợi ích của chủ đề
-
Mã nhỏ gọn hơn—giảm số lượng mã cần thiết để xử lý bộ sưu tập.
-
Ít biến trung gian hơn. Các biến can thiệp có thể gây ra lỗi. Càng ít thì càng dễ tránh những sai sót không mong muốn.
-
Mã trực quan. Một số nhà phát triển sẽ không đồng ý rằng các luồng trực quan hơn các phương pháp khác. Tuy nhiên, khi chúng ta đã quen với chúng, chúng trở nên trực quan hơn nhiều so với các phương pháp khác.
Cách đánh giá cấp phát bộ nhớ của đối tượng trong Java
Nguồn: DZone Bài viết này trình bày ba cách phổ biến nhất để đánh giá việc phân bổ bộ nhớ của đối tượng trong Java.Đánh giá trí nhớ bằng Profiler
Cách dễ nhất để ước tính bộ nhớ của một số đối tượng là xem trực tiếp vào bộ nhớ JVM bằng cách sử dụng một trình lược tả như Visual VM . Vấn đề với cách tiếp cận này là bạn cần kết nối với một JVM đang chạy, điều này có thể không thực hiện được đối với môi trường sản xuất vì lý do bảo mật.Đánh giá trí nhớ bằng dụng cụ
Một cách khác để ước tính bộ nhớ được phân bổ cho một đối tượng nhất định là sử dụng Công cụ. Nói một cách đơn giản, chúng ta cần tạo một lớp và biên dịch nó thành một JAR. Sau khi tạo JAR, chúng ta phải thực thi JVM của mình cùng với JAR đó. Bạn có thể tìm hiểu thêm về phương pháp này tại đây . Nhược điểm ở đây là cần phải thêm một tệp jar cụ thể vào JVM, tệp này có thể không được chấp nhận để sản xuất do các vấn đề bảo mật hoặc liên quan.Đánh giá trí nhớ bằng Thư viện JOL
Là một tùy chọn khác, chúng ta có thể sử dụng JOL Library . Đây là một thư viện rất mạnh có thể cung cấp ước tính chi tiết về trọng lượng của một đối tượng và bộ nhớ được phân bổ bởi một thể hiện đối tượng. Để sử dụng thư viện, chúng ta cần thêm một phụ thuộc:<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
Sau đó chúng ta có thể sử dụng nó như thế này:
out.println(GraphLayout.parseInstance(myObject).totalSize() / 1024000d + " MB")
ObjectSizeCalculator từ kho lưu trữ Twitter
Kho lưu trữ GitHub công khai của Twitter có một lớp công cụ tên là ObjectSizeCalculator có thể ước tính bộ nhớ được phân bổ cho một phiên bản đối tượng nhất định. Nó không tốn nhiều bộ nhớ hoặc thời gian để sử dụng. Quá trình đánh giá mất vài giây, ngay cả đối với các đối tượng lớn. Sử dụng lớp này khá đơn giản:ObjectSizeCalculator.getObjectSize(address)
Tôi khuyên dùng phương pháp này nhưng hãy nhớ rằng nó chỉ được hỗ trợ bởi Java Hotspot, OpenJDK và TwitterJDK.
GO TO FULL VERSION