1. Проверка

Мисля, че вече може да сте отегчени да научите How да свързвате потоци от данни. Искате най-накрая да направите нещо с данните.

Класът Streamима три стандартни метода, които не конструират потоци, а instead of това проверяват Howъв вид данни има в тях. Тези методи са: anyMatch(), allMatch()и noneMatch().

boolean anyMatch(rule)метод

Този метод проверява дали потокът има поне един елемент, който удовлетворява правилото, което се предава на метода. Ако има такъв елемент, методът връща true, в противен случай false.

Примери

Код Забележка
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

В последния пример първо запазваме само елементите, които са по-малки от нула, и след това проверяваме резултата, за да видим дали някой от филтрираните елементи е по-голям от нула. Разбира се, такива елементи вече не съществуват.

булев метод allMatch(rule).

Този метод проверява дали всички елементи в потока отговарят на правилото (известен също като предикат). Правилото се предава като аргумент на метода:

Код Забележка
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.allMatch(x -> x > 0);
true
(всички елементи по-големи от нула)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.allMatch(x -> x > 0);
false
(има ли елементи по-малки or равни на нула?)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(запазихме елементите, които са по-малки от нула)

В последния пример първо позволяваме само елементи, които са по-малки от нула, да преминат през филтъра и след това проверяваме дали всички запазени елементи са по-малки от нула. Проверката дава положителен резултат.

булев метод noneMatch(rule).

Методът noneMatch()проверява дали потокът няма елементи, които отговарят на предаденото правило. Това е като обратното на anyMatch()метода.

Код Забележка
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. Класове на полезност: Optionalклас

Понякога за програмистите е много неудобно да работят с nullпрепратки. Да предположим например, че сравнявате два низа. Ако и двете променливи не са null, тогава можете просто да извикате s1.equals(s2)и всичко ще работи. Но ако s1може null, тогава трябва да напишете code, който се справя с тази ситуация, за да избегнете NullPointerException.

Ето защо програмистите излязоха с Optional<T>полезния клас. Кодът му изглежда приблизително така:

Код Забележка
class Optional<Type>
{
   private final T 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;
   }
}










Проверява дали стойността не е null



Проверява дали стойността е null




Връща съхранената стойност. Извежда изключение, ако стойността е нула.







Връща съхранената ненулева стойност. Или ако съхранената стойност е null, тогава връща стойността, предадена като аргумент на метода.



Връща съхранената ненулева стойност or хвърля изключение, ако стойността е нулева.

Целта на този клас е просто да съхранява T обект (препратка към обект, чийто тип е T). Препратката към обект вътре в Optional<T>обект може да бъде null.

Този клас позволява на програмистите да пишат малко по-красив code. Да сравним:

Използване по избор Не се използва по избор
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)
}

Един Optionalобект винаги може да бъде сравнен с друг Optionalобект с помощта на equalsметода, дори ако те съхраняват nullпрепратки.

Най-просто казано, Optionalкласът ви позволява да пишете "красиви" проверки за nullи "красиви" действия в случай, че даден Optionalобект съхранява nullстойност.



3. Намиране на елементи

Да се ​​върнем в Streamкласа. Класът Streamима още 4 метода, които ви позволяват да търсите елементи в поток. Тези методи са findFirst(), findAny(), min()и max().

Optional<T> findFirst()метод

Методът findFirst()просто връща първия елемент в потока. Това е всичко, което прави.

По-интересното нещо, което трябва да се отбележи тук е, че методът не връща обект T, а по-скоро Optional<T>обвиващ обект. Това гарантира, че методът никога няма да се върне, nullслед като не успее да намери обект.

Пример:

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

За по-голяма яснота, нека разделим последния ред на няколко реда:

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

Последният get()метод просто извлича стойността, съхранена в Optionalобекта.

Optional<T> findAny()метод

Методът findAny()връща всеки елемент от потока и завършва там. Този метод е подобен на findFirst(), но е чудесен за потоци, използвани в паралелни операции.

Когато се обработват потоци паралелно, може вече да е намерен елемент в няHowва част от потока, но все още не е ясно дали е първият or не.

Ако много елементи отговарят на всички филтри и за програмиста е важно да получи точно първия от тях, тогава методът findFirst()е това, което трябва да се извика. Ако програмистът знае, че в действителност 0 or 1 елемент ще съответства на всички филтри, тогава е достатъчно просто да извика findAny()- и това ще бъде по-бързо.

Optional<T> min(Comparator<T>)метод

Методът min()използва comparatorобект за сравняване на всички елементи в потока и връща минималния елемент. Най-удобният начин за дефиниране на обект за сравнение е с ламбда функция.

Пример за търсене на най-късия низ:

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>)метод

Методът max()използва comparatorобект за сравняване на всички елементи в потока и връща максималния елемент. Най-удобният начин за дефиниране на обект за сравнение е с ламбда функция.

Пример за търсене на най-дългия низ:

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();