Перейти к основному содержимому

Как получить последний элемент потока в Java?

· 3 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Обзор

API Java Stream был основной функцией выпуска Java 8. Потоки представляют собой последовательности объектов с ленивой оценкой и предоставляют богатый, плавный и похожий на монадический API.

В этой статье мы кратко рассмотрим способы получения последнего элемента потока. Имейте в виду, что из-за природы потоков это не естественная операция . Всегда убедитесь, что вы не работаете с бесконечными потоками.

2. Использование API сокращения

Проще говоря, Reduce уменьшает набор элементов в потоке до одного элемента.

В этом случае мы уменьшим набор элементов, чтобы получить последний элемент в потоке. Имейте в виду, что этот метод будет возвращать детерминированные результаты только для последовательных потоков.

Давайте воспользуемся списком строковых значений , получим поток из списка и затем уменьшим:

List<String> valueList = new ArrayList<>();
valueList.add("Joe");
valueList.add("John");
valueList.add("Sean");

Stream<String> stream = valueList.stream();
stream.reduce((first, second) -> second)
.orElse(null);

Здесь поток сокращается до уровня, на котором остается только последний элемент. Если поток пуст, он вернет нулевое значение.

2. Использование функции пропуска

Другой способ получить последний элемент потока — пропустить все элементы перед ним . Этого можно добиться с помощью функции Skip класса Stream . Имейте в виду, что в данном случае поток используется дважды, поэтому производительность заметно снижается .

Давайте создадим список строковых значений и используем его функцию размера , чтобы определить, сколько элементов нужно пропустить, чтобы достичь последнего элемента.

Вот пример кода, получающего последний элемент с помощью skip :

List<String> valueList = new ArrayList<String>();
valueList.add("Joe");
valueList.add("John");
valueList.add("Sean");

long count = valueList.stream().count();
Stream<String> stream = valueList.stream();

stream.skip(count - 1).findFirst().get();

«Шон» оказывается последним элементом.

4. Получение последнего элемента бесконечного потока

Попытка получить последний элемент бесконечного потока привела бы к бесконечной последовательности вычислений, выполняемых для бесконечных элементов. Как skip , так и reduce не вернутся из выполнения оценки, если мы не ограничим бесконечный поток определенным количеством элементов, используя операцию ограничения .

Вот пример кода, где мы взяли бесконечный поток и попытались получить последний элемент:

Stream<Integer> stream = Stream.iterate(0, i -> i + 1);
stream.reduce((first, second) -> second).orElse(null);

Следовательно, поток не вернется из оценки и в конечном итоге остановит выполнение программы .

5. Вывод

Мы видели разные способы получения последнего элемента потока как с помощью API сокращения , так и с помощью Skip . Мы также рассмотрели, почему это невозможно с бесконечными потоками.

Мы видели, что получить последний элемент из Stream непросто по сравнению с его извлечением из других структур данных. Это связано с ленивым характером потоков , которые не оцениваются, пока не будет вызвана терминальная функция, и мы никогда не узнаем, является ли текущий оцениваемый элемент последним.

Фрагменты кода можно найти на GitHub.