Стримы в Java
Нахождение первого элемента в стриме
[Нахождение первого элемента в стриме]Если у вас есть стрим каких-то элементов и вам нужно найти первый элемент, это легко сделать с помощью метода findFirst.
Поиск первого элемента в стриме
Для нахождения первого элемента в стриме воспользуемся методом findFirst. Он вернёт объект типа Optional, на котором мы вызовем метод orElse(null) для того, чтобы извлечь хранящийся внутри его элемент (или значение null, если элемент отсутствует):
public static <T> T getFirstElementInStream(Stream<T> stream) { return stream .findFirst() .orElse(null); }Проверим это на тестовых данных:
[]
Исходный код
import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class GetFirstElementInStream { public static void main(String[] args) { List<String> ids = Arrays.asList("111", "222", "333", "444", "555", "666", "777"); System.out.println("Все элементы: " + ids); String firstElement = getFirstElementInStream(ids.stream()); System.out.println("Первый элемент: " + firstElement); } public static <T> T getFirstElementInStream(Stream<T> stream) { return stream .findFirst() .orElse(null); } }
Нахождение последнего элемента в стриме
[Нахождение последнего элемента в стриме]Иногда возникает задача нахождения последнего элемента в стриме. Первый элемент можно получить с помощью метода findFirst, но как же найти последний?
Поиск последнего элемента
Для нахождения последнего элемента можно воспользоваться оператором reduce, который принимает на вход два элемента стрима и возвращает один:
public static <T> T getLastElement(Stream<T> stream) { return stream .reduce((e1, e2) -> e2) .orElse(null); }В данном случае нам нужно всегда возвращать второй аргумент их двух переданных — и, в конце концов, мы получим на выходе последний элемент. Точнее, получим Optional, который может содержать элемент или быть пустым.
[]
Исходный код
import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class GetLastElementInStream { public static void main(String[] args) { List<String> ids = Arrays.asList("111", "222", "333", "444", "555", "666", "777"); System.out.println("Все элементы: " + ids); String lastElement = getLastElement(ids.stream()); System.out.println("Последний элемент: " + lastElement); } public static <T> T getLastElement(Stream<T> stream) { return stream .reduce((e1, e2) -> e2) .orElse(null); } }
Конвертация Iterator в Stream
[Конвертация Iterator в Stream]Иногда требуется преобразовать объект типа Iterator в Stream. Для этих целей в Java есть вспомогательный метод StreamSupport.stream:
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)
Первый аргумент это объект типа Spliterator. Мы его получим из Iterator/Iterable. Второй аргумент включает параллельную обработку Stream.
Преобразование Iterator в Stream
public static <T> Stream<T> asStream(Iterator<T> sourceIterator) { Iterable<T> iterable = () -> sourceIterator; return StreamSupport.stream(iterable.spliterator(), false); }Проверка:
List<String> list = Arrays.asList("Alice", "Bob", "Carl"); Iterator<String> iterator = list.iterator(); asStream(iterator) .map(name -> "Hello, " + name + "!") .forEach(System.out::println);
Как объединить два стрима
[Как объединить два стрима]Иногда возникает необходимость объединить два различных стрима. В это статье мы расскажем вам, как это сделать несколькими способами.
Объединение с помощью Stream.concat
Это наиболее популярный и удобный способ объединения двух стримов.
Допустим, у вас есть два стрима:
Stream<String> s1 = Arrays.stream(new String[]{"A", "B", "C"}); Stream<String> s2 = Arrays.stream(new String[]{"D", "E", "F"});Их можно объединить с помощью метода Stream.concat:
Stream.concat(s1, s2).forEach(System.out::println);
Stream.concat объединит элементы из двух стримов в один стрим.
Объединение стримов IntStream, LongStream, DoubleStream
Если вам требуется объединить элементы из стримов типа IntStream, LongStream или DoubleStream, можно воспользоваться тем же методом concat:
IntStream i1 = IntStream.range(1, 5); IntStream i2 = IntStream.range(5, 11); IntStream.concat(i1, i2).forEach(System.out::println);
Аналогичным образом объединяются элементы в стримах LongStream и DoubleStream.
Исходный код
import java.util.Arrays; import java.util.stream.IntStream; import java.util.stream.Stream; public class MergeTwoStreamsExample { public static void main(String[] args) { Stream<String> s1 = Arrays.stream(new String[]{"A", "B", "C"}); Stream<String> s2 = Arrays.stream(new String[]{"D", "E", "F"}); Stream.concat(s1, s2).forEach(System.out::println); IntStream i1 = IntStream.range(1, 5); IntStream i2 = IntStream.range(5, 11); IntStream.concat(i1, i2).forEach(System.out::println); // LongStream.concat(...) // DoubleStream.concat(...) } }
Как суммировать BigDecimal с помощью Stream
[Как суммировать BigDecimal с помощью Stream]Начиная с Java 8, мы можем суммировать BigDecimal с помощью метода Stream.reduce().
Как суммировать BigDecimal
Сначала создадим список, состоящий из элементов BigDecimal:
List<BigDecimal> numbers = new ArrayList<>(); numbers.add(BigDecimal.valueOf(10.1)); numbers.add(BigDecimal.valueOf(89.9)); numbers.add(BigDecimal.valueOf(50.5));
Затем получим из списка стрим его элементов и воспользуемся методом Stream.reduce для того, чтобы суммировать все элементы стрима:
BigDecimal total = numbers.stream().reduce(BigDecimal.ZERO, BigDecimal::add); System.out.println(total); // 150.5
Метод Stream.reduce принимает два аргумента – начальное значение и функцию-аккумулятор, которая складывает два числа (предыдущее значение аккумулятора и следующий элемент в стриме).
Исходный код
import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; public class SumBigDecimalStream { public static void main(String[] args) { List<BigDecimal> numbers = new ArrayList<>(); numbers.add(BigDecimal.valueOf(10.1)); numbers.add(BigDecimal.valueOf(89.9)); numbers.add(BigDecimal.valueOf(50.5)); BigDecimal total = numbers.stream().reduce(BigDecimal.ZERO, BigDecimal::add); System.out.println(total); // 150.5 } }
Поиск дубликатов в Stream
[Поиск дубликатов в Stream]В данной статье мы расскажем вам, как находить дублирующиеся элементы в стримах. Допустим, у вас есть некий стрим с элеменетами, которые могут повторяться, и у вам нужно найти такие элементы. Эту задачу можно решить несколькими способами.
Варианты решения задачи
Есть несколько вариантов найти дубликаты в стриме:
- С помощью дополнительного объекта Set
- С помощью метода Collectors.groupingBy
- С помощью утилитного метода Collections.frequency
Поиск дубликатов с помощью Set
Сначала инициализируем вспомогательный Set, с помощью которого мы будем проверять, является ли следующий элемент стрима дубликатом:
Set<T> elements = new HashSet<>();
Затем в стриме будем добавлять каждый элемент из коллекции в Set с помощью метода add(). Этот метод возвращает true в том случае, если этот элемент ранее не был добавлен в Set:
collection.stream() .filter(e -> !elements.add(e)) .collect(Collectors.toSet());Таким образом, мы отфильтруем те элементы, которые встречаются в коллекции более одного раза.
Таким образом, полный код нашего метода может выглядеть следующим образом:
public static <T> Set<T> findDuplicates(Collection<T> collection) { Set<T> elements = new HashSet<>(); return collection.stream() .filter(e -> !elements.add(e)) .collect(Collectors.toSet()); }Проверим его с помощью тестовых данных:
public static void main(String[] args) { List<String> names = Arrays.asList("Alice", "Bob", "Alice", "Carl", "Don", "Eugene", "Carl"); System.out.println("Все элементы: " + names); Set<String> duplicates = findDuplicates(names); System.out.println("Дубликаты: " + duplicates); }