Получить последний элемент потока / списка в одной строке
как я могу получить последний элемент потока или списка в следующем коде?
здесь data.careas это List<CArea>:
CArea first = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal).findFirst().get();
CArea last = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal).collect(Collectors.toList()).; //how to?
как вы можете видеть, получая первый элемент, с определенным filter, это не сложно.
однако получение последнего элемента в одном лайнере-настоящая боль:
- кажется, я не могу получить его непосредственно от
Stream. (Это имело бы смысл только для конечных потоков) - также кажется, что вы не могу получить такие вещи, как
first()иlast()СListинтерфейс, который действительно боль.
я не вижу никаких аргументов для не предоставления first() и last() метод List интерфейс, так как элементы там упорядочены, и, кроме того, размер известен.
но согласно оригинальному ответу: как получить последний элемент конечного Stream?
лично, это самое близкое, что я мог сделать:
int lastIndex = data.careas.stream()
.filter(c -> c.bbox.orientationHorizontal)
.mapToInt(c -> data.careas.indexOf(c)).max().getAsInt();
CArea last = data.careas.get(lastIndex);
это с помощью
indexOf на каждом элементе, который, скорее всего, не вы вообще хотите, как это может ухудшить производительность. 7 ответов:
можно получить последний элемент с помощью метода трансляция::уменьшение. Следующий список содержит минимальный пример для общего случая:
Stream<T> stream = ...; // sequential or parallel stream Optional<T> last = stream.reduce((first, second) -> second);эта реализация работает для всех заказал потоков (включая потоки, создаваемые из списки). Ибо ненумерованный потоки по понятным причинам не указано, какой элемент будет возвращен.
реализация работает для обоих последовательный и параллельные потоки. Это может быть удивительно на первый взгляд, и, к сожалению, в документации это не указано явно. Тем не менее, это важная особенность потоков, и я пытаюсь ее прояснить:
- Javadoc для метода трансляция::уменьшение и "составляет не ограничено для выполнения последовательно".
- Javadoc также требует что за " функция аккумулятора должна быть ассоциативные,немешай,без гражданства функция для объединения двух значений", что, очевидно, относится к лямбда-выражению
(first, second) -> second.- Javadoc для сокращение операций гласит: "классы потоков имеют несколько форм общих операций сокращения, называемых уменьшить() и collect () [..]" и "правильно построенная операция reduce по своей сути распараллеливается, если функции, используемые для обработки элементов ассоциативные и без гражданства."
документация для тесно связанных коллекторами еще более явная: "обеспечить последовательный и параллельных выполнений производства эквивалентные результаты, в функции коллектора должны удовлетворять идентификатору и ассоциативность ограничения."
вернемся к исходному вопросу: в следующем коде хранится ссылка на последний элемент в переменной
lastи выдает исключение, если поток пуст. Сложность линейна по длине потока.CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .reduce((first, second) -> second).get();
Если у вас есть коллекция (или более общая итерационная), вы можете использовать Google Guava
Iterables.getLast(myIterable)как удобно, проявляющаяся.
поскольку неясно, является ли это частью спецификации API для
reduceчтобы подчиниться приказу встречи, как насчет:CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .max((e1, e2) -> data.careas.indexOf(e1) - data.careas.indexOf(e2)).get();
вы также можете использовать функцию skip (), как показано ниже...
long count = data.careas.count(); CArea last = data.careas.stream().skip(count - 1).findFirst().get();это очень простой в использовании.
Как уже упоминалось @nosid, это можно сделать с помощью reduce. Другой способ сделать это было бы обратить поток, а затем получить первый элемент
CArea last = data.careas.stream() .filter(c -> c.bbox.orientationHorizontal) .sorted((a, b)-> -1) .findFirst().get();
можно использовать
java.util.Collectionsиспользуя следующий статический метод:Collections.max(yourList);из документов:
возвращает максимальный элемент данного набора, согласно * естественный заказ ее элементов. [...]
Comments