Страницы

Поиск по вопросам

пятница, 14 февраля 2020 г.

Как получить каждый n-ый элемент из списка с помощью Stream API?

#java #java_8 #java_stream #функциональное_программирование


Предположим, у меня есть такой список:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


Можно ли использовать Java Stream API для переноса каждого второго элемента из этого
списка, чтобы получить такой список?

[1, 3, 5, 7, 9]


Или, может быть, каждый третий элемент?

[1, 4, 7, 10]


По сути, я ищу такую функцию, чтобы взять каждый n-ый элемент из потока:

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List list2 = list.stream().takenth(3).collect(Collectors.toList());
System.out.println(list2);
// => [1, 4, 7, 10]

    


Ответы

Ответ 1



Одним из главных мотивов для введения потоков Java было разрешение параллельных операций. Это привело к требованию, чтобы операции Java Streams, такие как map и filter, не зависели от положения элемента в потоке или элементов вокруг него. У этого есть преимущество, оно позволяет легко разделять потоки для параллельной обработки. Недостатком является сложность некоторых операций. Таким образом, нет простого способа сделать что-то такое, например, взять каждый n-ый предмет или сопоставить каждый предмет сумме всех предыдущих предметов. Самый простой способ выполнить ваше требование - использовать индекс списка: List list = ...; return IntStream.range(0, list.size()) .filter(n -> n % 3 == 0) //3 - каждый 3-ий элемент .mapToObj(list::get) .collect(Collectors.toList()); Примечание от Sergey Gornostaev: Решение рабочее, но должен заметить, подобное применение стримов - это антипаттерн. Не желательно работать с данными за пределами стрима. Как только появляется идея об обращении к переменной, стоит насторожиться и подумать "Я использую стримы неправильно или стримы тут вообще не подходят?" Используя Stream.iterate List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int skip = 3; int size = list.size(); // Limit to carefully avoid IndexOutOfBoundsException int limit = size / skip + Math.min(size % skip, 1); List result = Stream.iterate(0, i -> i + skip) .limit(limit) .map(list::get) .collect(Collectors.toList()); System.out.println(result); // [1, 4, 7, 10] Используя библиотеку Guava(GitHub): Streams .mapWithIndex(stream, SimpleImmutableEntry::new) .filter(entry -> entry.getValue() % 3 == 0) .map(Entry::getKey) .collect(Collectors.toList()); Используя библиотеку AbacusUtil: Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .filter(MutableInt.of(0), (e, idx) -> idx.getAndDecrement() % 3 == 0) .println(); Используя библиотеку jOOλ и ее метод zipWithIndex(): System.out.println( Seq.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .zipWithIndex() // This produces a Tuple2(yourvalue, index) .filter(t -> t.v2 % 3 == 0) // Filter by the index .map(t -> t.v1) // Remove the index again .toList() );

Комментариев нет:

Отправить комментарий