1. Проверка

Думаю, вам уже скучно изучать, как конструировать цепочки потоков данных. Хочется наконец-то с этими данными что-то делать.

У класса Stream есть три стандартных метода, которые не конструируют потоки, а проверяют, что за данные находятся в этих потоках. Это методы: anyMatch(), allMatch() и noneMatch().

Метод boolean anyMatch(правило)

Этот метод проверяет, что в потоке есть хотя бы один элемент, который удовлетворяет правилу, которое передается в метод. Если такой элемент есть, метод возвращает 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

В последнем примере мы сначала отфильтровываем (пропускаем через фильтр) все элементы меньше нуля, а затем уже среди них проводим проверку, есть ли хотя бы один элемент больше нуля. Ясное дело, таких элементов там уже нет.

Метод boolean allMatch(правило)

Этот метод проверяет, что все элементы в потоке соответствуют правилу. Правило передается в метод в качестве параметра:

Код Примечание
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
(есть элементы меньше или равны нулю)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(отфильтровали элементы меньше нуля)

В последнем примере мы сначала пропускаем через фильтр только элементы меньше нуля, а потом уже среди них выполняем проверку, что все элементы меньше нуля. Проверка проходит успешно.

Метод boolean noneMatch(правило)

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

4
Задача
Java Core,  6 уровень5 лекция
Недоступна
join: в нужное время в нужном месте
Метод join — очень полезен и часто используется для завершения работы нити. Подумайте, в каком месте и для какого объекта нужно вызвать этот метод, чтобы результат выводился по-порядку сначала для firstThread, а потом для secondThread. Ваша задача — вызвать join в нужном месте.
18
Задача
Java Core,  6 уровень5 лекция
Недоступна
Horse Racing
Уж лучше программировать, чем делать ставки... Тем не менее, скачки и прочие гонки прекрасно иллюстрируют многопоточность! Итак, разберитесь, что делает код, и реализуйте метод, который будет считать количество лошадей, пришедших к финишу. И ещё, нужно обязательно подождать, пока аутсайдеры также закончат гонку.

2. Служебные классы: класс Optional

Иногда программистам очень неудобно работать с ссылками на null. Например, вы сравниваете две строки. Если обе переменные не null, тогда можно просто вызвать s1.equals(s2), и все будет работать. А вот если s1 может быть null, придется писать код, который учитывает эту ситуацию, чтобы не возникло NullPointerException.

Поэтому программисты придумали служебный класс Optional<T>. Выглядит его код примерно так:

Код Примечание
class Optional<Tип>
{
   private final Tип value;
   private Optional() { this.value = null;}
   private Optional(value) { this.value = value;}
   public static <Tип> Optional<Tип> of(Tип value)
   {
      return new Optional<Tип>(value);
   }

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

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

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

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

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










Проверяет, что внутри находится значение (ссылка не null)



Проверяет, что объект хранит ссылку на null




Возвращает значение, которое хранит. Кидает исключение, если значения нет.







Возвращает значение, или если внутри хранится null, то переданное в метод второе значение



Возвращает значение или кидает исключение, если значения нет.

Цель этого класса – просто хранить в себе объект T (ссылку на объект типа T). Ссылка на объект внутри класса Optional<T> может быть null.

Этот класс позволяет писать программистам код немного красивее. Сравните:

С использованием Optional Без использования Optional
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.


9
Задача
Java Core,  6 уровень5 лекция
Недоступна
Продвижение на политических дебатах
Наш кандидат — Иванов! И мы ему немного поможем, сделав так, чтобы он толкнул речь, а затем снова речь, и ещё раз — речь на политических дебатах. Подсобим ему немного, сделав так, чтобы он разговаривал до тех пор, пока не завершится всё свободное время. Нити нам в помощь!

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, "Привет", "как", "дела?");
String str = list.stream().findFirst().get(); // Привет

Давайте для большей ясности распишем последнюю строку в несколько строк:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привет", "как", "дела?");

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

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

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

Метод findAny() возвращает любой элемент из потока и на этом завершается. Этот метод — это аналог метода findFirst(), только для потоков, которые обрабатываются параллельно.

При параллельной обработке потоков может случиться такая ситуация, что в какой-то части потока элемент уже найден, но пока еще не понятно, будет он первым или нет.

Если элементов, которые прошли все фильтры, много и для программиста принципиально получить именно первый из них, следует вызывать метод findFirst(). Если программист знает, что реально через все фильтры пройдет 0 или 1 элемент, тогда достаточно просто вызвать findAny() — так будет быстрее.

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

Метод min() сравнивает все элементы потока с помощью объекта comparator и возвращает минимальный элемент. Удобнее всего задать объект-компаратор с помощью лямбда-функции.

Пример — поиск строки с минимальной длиной:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привет", "как", "дела?");
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, "Привет", "как", "дела?");
String max = list.stream().max( (s1, s2)-> s1.length()-s2.length() ).get();
4
Задача
Java Core,  6 уровень5 лекция
Недоступна
Справедливость
Справедливость — имя древнего террианского божества, которого в природе никто не видел. Зато в системах, придуманных человеком, эту самую Справедливость, иногда встречают. Итак, перед нами мыши. Почему-то один из мышей, альфа-самец, ест первым, а остальные ждут. Разберитесь, почему так и... удалите вызов этого метода.
9
Задача
Java Core,  6 уровень5 лекция
Недоступна
Расставь вызовы методов join()
Сначала кошка рожает котят. Потом все котята вылезают из корзинки в произвольном порядке. В конце кошка собирает их назад в корзинку. Все события для одной кошки могут быть перемешаны с событиями для другой кошки. А теперь реализуйте это с помощью join().