1. Weryfikacja

Myślę, że znudziło Cię już uczenie się, jak konstruować łańcuchy przepływu danych. Chciałbym w końcu coś zrobić z tymi danymi.

Klasa Streamma trzy standardowe metody, które nie konstruują strumieni, ale sprawdzają, jakie dane są w tych strumieniach. Są to metody: anyMatch(), allMatch()i noneMatch().

metodaboolean anyMatch(правило)

Ta metoda sprawdza, czy w strumieniu znajduje się co najmniej jeden element, który spełnia regułę przekazaną do metody. Jeśli taki element istnieje, metoda zwraca true, w przeciwnym razie — false.

Przykłady

Kod Notatka
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

W ostatnim przykładzie najpierw odfiltrowujemy (przepuszczamy przez filtr) wszystkie elementy mniejsze od zera, a następnie sprawdzamy, czy wśród nich jest przynajmniej jeden element większy od zera. Oczywiście takich elementów już nie ma.

metoda logiczna allMatch(reguła)

Ta metoda sprawdza, czy wszystkie elementy w strumieniu pasują do reguły. Reguła jest przekazywana do metody jako parametr:

Kod Notatka
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.allMatch(x -> x > 0);
true
(wszystkie elementy są większe od zera)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.allMatch(x -> x > 0);
false
(są elementy mniejsze lub równe zeru)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(filtrowane elementy mniejsze od zera)

W ostatnim przykładzie najpierw przepuszczamy przez filtr tylko elementy mniejsze od zera, a następnie sprawdzamy, czy wszystkie elementy są mniejsze od zera. Weryfikacja powiodła się.

metoda boolean noneMatch(reguła)

Metoda noneMatch()sprawdza, czy w strumieniu nie ma elementów pasujących do przekazanej reguły. Odwrotność w znaczeniu metody do metody anyMatch().

Kod Notatka
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. Klasy użytkowe: klasaOptional

Czasami praca z odniesieniami do plików null. Na przykład porównujesz dwa łańcuchy. Jeśli obie zmienne nie są null, możesz po prostu zadzwonić s1.equals(s2)i wszystko będzie działać. Ale jeśli s1być może null, będziesz musiał napisać kod, który uwzględni tę sytuację, aby NullPointerException.

Więc programiści wymyślili klasę użytkową Optional<T>. Jego kod wygląda następująco:

Kod Notatka
class Optional<typ T>
{
   private final typ T value;
   private Optional() { this.value = null;}
   private Optional(value) { this.value = value;}
   public static <typ T> Optional<typ T> of(typ T value)
   {
      return new Optional<typ T>(value);
   }

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

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

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

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

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










Sprawdza, czy wewnątrz znajduje się wartość (referencja nie null)



Sprawdza, czy obiekt zawiera referencję do null




Zwraca przechowywaną wartość. Zgłasza wyjątek, jeśli nie ma wartości.







Zwraca wartość lub jeśli jest przechowywana wewnątrz null, to druga wartość przekazywana do metody



Zwraca wartość lub zgłasza wyjątek, jeśli nie ma wartości.

Celem tej klasy jest po prostu przechowywanie obiektu T (referencja do obiektu typu T). Odwołaniem do obiektu w klasie Optional<T>może być null.

Ta klasa pozwala programistom pisać trochę ładniejszy kod. Porównywać:

Korzystanie z opcjonalnego Bez użycia opcji
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)
}

Jeden obiekt Optionalzawsze można porównać z innym obiektem Optionalza pomocą metody equals, nawet jeśli przechowuje on odniesienia do null.

Z grubsza rzecz biorąc, klasa Opcjonalna pozwala „piękniej” pisać kontrole nulli akcje na wypadek, gdyby obiekt Optionalbył przechowywany w null.



3. Wyszukaj elementy

Wróćmy do klasy Stream. Klasa Streamposiada jeszcze 4 metody pozwalające na wyszukiwanie elementów w strumieniu. Są to metody findFirst(), findAny(), min()i max().

metodaOptional<T> findFirst()

Metoda findFirst()po prostu zwraca pierwszy element ze strumienia i już – to kończy jej pracę.

Co ciekawsze, metoda nie zwraca obiektu typu T, ale opakowanie na nim - obiekt typu Optional<T>. Ma to na celu zapewnienie, że metoda nigdy nie znajdzie obiektu i nie zwróci null.

Przykład:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
String str = list.stream().findFirst().get(); // Привет

Zapiszmy ostatni wiersz w kilku wierszach, aby uzyskać większą przejrzystość:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");

Stream<String> stream = list.stream();
Optional<String> result = stream.findFirst();
String str = result.get(); // Привет

Ostatnią metodą get()jest po prostu wyciągnięcie wartości przechowywanej w pliku Optional.

metodaOptional<T> findAny()

Metoda findAny()zwraca dowolny element ze strumienia i na tym się kończy. Ta metoda jest podobna do metody findFirst()tylko dla wątków, które są przetwarzane równolegle.

Podczas równoległego przetwarzania strumieni może się zdarzyć taka sytuacja, że ​​w jakiejś części strumienia element został już znaleziony, ale nie jest jeszcze jasne, czy będzie on pierwszy, czy nie.

Jeśli istnieje wiele elementów, które przeszły wszystkie filtry i ważne jest, aby programista otrzymał dokładnie pierwszy z nich, plik findFirst(). Jeśli programista wie, że faktycznie przez wszystkie filtry przejdzie 0 lub 1 element, to wystarczy zwykłe wywołanie findAny()- będzie szybciej.

metodaOptional<T> min(Comparator<T>)

Metoda min()porównuje wszystkie elementy strumienia z obiektem comparatori zwraca element minimalny. Najwygodniejszym sposobem zdefiniowania obiektu porównawczego jest użycie funkcji lambda.

Przykład - wyszukiwanie ciągu znaków o minimalnej długości:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
String min = list.stream().min( (s1, s2)-> s1.length()-s2.length() ).get();

metodaOptional<T> max(Comparator<T>)

Metoda max()porównuje wszystkie elementy strumienia z obiektem comparatori zwraca element maksymalny. Najwygodniejszym sposobem zdefiniowania obiektu porównawczego jest użycie funkcji lambda.

Przykład - wyszukiwanie ciągu znaków o maksymalnej długości:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
String max = list.stream().max( (s1, s2)-> s1.length()-s2.length() ).get();