1. Kiểm tra

Tôi nghĩ bạn có thể đã chán với việc học cách xâu chuỗi các luồng dữ liệu lại với nhau. Bạn muốn cuối cùng làm điều gì đó với dữ liệu.

Lớp Streamcó ba phương thức tiêu chuẩn không xây dựng luồng mà thay vào đó kiểm tra loại dữ liệu nào có trong đó. Những phương pháp này là: anyMatch(), allMatch(), và noneMatch().

boolean anyMatch(rule)phương pháp

Phương thức này kiểm tra xem luồng có ít nhất một phần tử thỏa mãn quy tắc được truyền cho phương thức hay không. Nếu có một phần tử như vậy, phương thức trả về true, nếu không thì false.

ví dụ

Mã số Ghi chú
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).anyMatch(x -> x > 0);

false

Trong ví dụ trước, trước tiên chúng tôi chỉ giữ lại các phần tử nhỏ hơn 0, sau đó chúng tôi kiểm tra kết quả để xem liệu có bất kỳ phần tử nào được lọc lớn hơn 0 hay không. Tất nhiên, những yếu tố như vậy không còn nữa.

phương thức boolean allMatch(quy tắc)

Phương thức này kiểm tra xem tất cả các phần tử trong luồng có khớp với quy tắc hay không (còn được gọi là vị từ). Quy tắc được truyền dưới dạng đối số cho phương thức:

Mã số Ghi chú
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.allMatch(x -> x > 0);
true
(tất cả các phần tử lớn hơn 0)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.allMatch(x -> x > 0);
false
(có phần tử nào nhỏ hơn hoặc bằng 0 không?)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(chúng tôi đã giữ lại các phần tử nhỏ hơn 0)

Trong ví dụ trước, trước tiên chúng tôi chỉ cho phép các phần tử nhỏ hơn 0 đi qua bộ lọc, sau đó chúng tôi kiểm tra xem tất cả các phần tử được giữ lại có nhỏ hơn 0 hay không. Việc kiểm tra mang lại một kết quả tích cực.

phương thức boolean noneMatch(quy tắc)

Phương noneMatch()thức kiểm tra xem luồng có phần tử nào khớp với quy tắc đã thông qua hay không. Nó giống như sự đối lập của anyMatch()phương pháp.

Mã số Ghi chú
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).noneMatch(x -> x > 0);

true


2. Các lớp tiện ích: Optionalđẳng cấp

Đôi khi rất bất tiện cho người lập trình khi làm việc với nullcác tham chiếu. Ví dụ: giả sử bạn đang so sánh hai chuỗi. Nếu cả hai biến đều không null, thì bạn chỉ cần gọi s1.equals(s2)và mọi thứ sẽ hoạt động. Nhưng nếu s1có thể null, thì bạn phải viết mã xử lý tình huống này để tránh lỗi NullPointerException.

Đó là lý do tại sao các lập trình viên đã nghĩ ra Optional<T>lớp tiện ích. Mã của nó trông đại khái như thế này:

Mã số Ghi chú
class Optional<Type>
{
   private final Type value;
   private Optional() { this.value = null;}
   private Optional(value) { this.value = value;}
   public static <Type> Optional<Type> of(Type value)
   {
      return new Optional<Type>(value);
   }

   public boolean isPresent()
   {
      return value != null;
   }

   public boolean isEmpty()
   {
      return value == null;
   }

   public Type get()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }

   public Type orElse(Type other)
   {
      return value != null ? value : other;
   }

   public Type orElseThrow()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }
}










Kiểm tra xem giá trị có phải không null



Kiểm tra xem giá trị có null




Trả về giá trị được lưu trữ hay không. Ném một ngoại lệ nếu giá trị là null.







Trả về giá trị khác null được lưu trữ. Hoặc nếu giá trị được lưu trữ là null, sau đó trả về giá trị được truyền dưới dạng đối số phương thức



Trả về giá trị khác null được lưu trữ hoặc đưa ra một ngoại lệ nếu giá trị là null.

Mục đích của lớp này chỉ đơn giản là lưu trữ một đối tượng T (một tham chiếu đến một đối tượng có kiểu là T). Tham chiếu đối tượng bên trong một Optional<T>đối tượng có thể là null.

Lớp này cho phép các lập trình viên viết mã đẹp hơn một chút. Hãy so sánh:

Sử dụng tùy chọn Không sử dụng Tùy chọn
public void printString(String s)
{
   Optional<String> str = Optional.ofNullable(s);
   System.out.println(str.orElse(""));
}
public void printString(String s)
{
   String str = s != null ? s : "";
   System.out.println(str)
}

Một Optionalđối tượng luôn có thể được so sánh với một Optionalđối tượng khác bằng equalsphương thức này, ngay cả khi chúng lưu trữ nullcác tham chiếu.

Nói một cách đơn giản, Optionallớp này cho phép bạn viết các kiểm tra "đẹp" nullvà các hành động "đẹp" trong trường hợp một Optionalđối tượng lưu trữ một nullgiá trị.



3. Tìm phần tử

Hãy trở lại Streamlớp học. Lớp này Streamcó thêm 4 phương thức cho phép bạn tìm kiếm các phần tử trong luồng. Những phương pháp này là findFirst(), findAny(), min(), và max().

Optional<T> findFirst()phương pháp

Phương thức này findFirst()chỉ trả về phần tử đầu tiên trong luồng. Đó là tất cả những gì nó làm.

Điều thú vị hơn cần lưu ý ở đây là phương thức này không trả về một Tđối tượng, mà là một Optional<T>đối tượng bao bọc. Điều này đảm bảo rằng phương thức sẽ không bao giờ quay lại nullsau khi không tìm thấy đối tượng.

Ví dụ:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String str = list.stream().findFirst().get(); // Hello

Để làm rõ hơn, hãy chia dòng cuối cùng thành nhiều dòng:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");

Stream<String> stream = list.stream();
Optional<String> result = stream.findFirst();
String str = result.get(); // Hello

Phương thức cuối cùng get()chỉ đơn giản là truy xuất giá trị được lưu trữ bên trong Optionalđối tượng.

Optional<T> findAny()phương pháp

Phương findAny()thức trả về bất kỳ phần tử nào từ luồng và kết thúc ở đó. Phương pháp này tương tự như findFirst(), nhưng nó rất tốt cho các luồng được sử dụng trong các hoạt động song song.

Khi xử lý các luồng song song, có thể một phần tử đã được tìm thấy trong một số phần của luồng, nhưng vẫn chưa rõ đó có phải là phần tử đầu tiên hay không.

Nếu nhiều phần tử khớp với tất cả các bộ lọc và điều quan trọng là lập trình viên phải lấy chính xác phần tử đầu tiên trong số chúng, thì phương findFirst()thức nên được gọi. Nếu lập trình viên biết rằng trong thực tế, 0 hoặc 1 phần tử sẽ khớp với tất cả các bộ lọc, thì chỉ cần gọi là đủ findAny()- và điều này sẽ nhanh hơn.

Optional<T> min(Comparator<T>)phương pháp

Phương thức này min()sử dụng một comparatorđối tượng để so sánh tất cả các phần tử trong luồng và trả về phần tử tối thiểu. Cách thuận tiện nhất để xác định đối tượng so sánh là sử dụng hàm lambda.

Ví dụ tìm kiếm chuỗi ngắn nhất:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String min = list.stream().min( (s1, s2)-> s1.length()-s2.length() ).get();

Optional<T> max(Comparator<T>)phương pháp

Phương thức này max()sử dụng một comparatorđối tượng để so sánh tất cả các phần tử trong luồng và trả về phần tử lớn nhất. Cách thuận tiện nhất để xác định đối tượng so sánh là sử dụng hàm lambda.

Ví dụ tìm kiếm chuỗi dài nhất:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String max = list.stream().max( (s1, s2)-> s1.length()-s2.length() ).get();