Как перебрать поток с индексами
1. обзор
Java 8Streamsне являются коллекциями, и к элементам нельзя получить доступ с помощью их индексов, но есть еще несколько уловок, чтобы сделать это возможным.
В этой короткой статье мы рассмотрим, как перебиратьStream, используяIntStream,StreamUtils, EntryStream, иVavr‘sStream.
2. Использование простой Java
Мы можем перемещаться поStream, используя диапазонInteger, а также извлекать выгоду из того факта, что исходные элементы находятся в массиве или коллекции, доступной по индексам.
Давайте реализуем метод, который выполняет итерацию с индексами и демонстрирует этот подход.
Проще говоря, мы хотим получить массив изStrings и выбирать только даже проиндексированные элементы:
public List getEvenIndexedStrings(String[] names) {
List evenIndexedNames = IntStream
.range(0, names.length)
.filter(i -> i % 2 == 0)
.mapToObj(i -> names[i])
.collect(Collectors.toList());
return evenIndexedNames;
}
Давайте теперь протестируем реализацию:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Afrim", "Besim", "Durim");
List actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
3. ИспользуяStreamUtils
Другой способ итерации с индексами может быть выполнен с использованием методаzipWithIndex() дляStreamUtils из библиотекиproton-pack (последнюю версию можно найтиhere).
Во-первых, вам нужно добавить его в свойpom.xml:
com.codepoetics
protonpack
1.13
Теперь посмотрим на код:
public List> getEvenIndexedStrings(List names) {
List> list = StreamUtils
.zipWithIndex(names.stream())
.filter(i -> i.getIndex() % 2 == 0)
.collect(Collectors.toList());
return list;
}
Следующие тесты этот метод и успешно проходит:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStrings() {
List names = Arrays.asList(
"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim");
List> expectedResult = Arrays.asList(
Indexed.index(0, "Afrim"),
Indexed.index(2, "Besim"),
Indexed.index(4, "Durim"));
List> actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
4. ИспользуяStreamEx
Мы также можем выполнять итерацию с индексами, используяfilterKeyValue() классаEntryStream из библиотекиStreamEx (последнюю версию можно найтиhere). Во-первых, нам нужно добавить его в нашpom.xml:
one.util
streamex
0.6.5
Давайте посмотрим на простое применение этого метода на нашем предыдущем примере:
public List getEvenIndexedStringsVersionTwo(List names) {
return EntryStream.of(names)
.filterKeyValue((index, name) -> index % 2 == 0)
.values()
.toList();
}
Мы воспользуемся аналогичным тестом, чтобы проверить это:
@Test
public void whenCalled_thenReturnListOfEvenIndexedStringsVersionTwo() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Afrim", "Besim", "Durim");
List actualResult
= StreamIndices.getEvenIndexedStrings(names);
assertEquals(expectedResult, actualResult);
}
5. Итерация с использованием Vavre‘sStream
Другой вероятный способ итерации - использование методаzipWithIndex() из реализацииVavr (ранее известного какJavaslang) sStream:
public List getOddIndexedStringsVersionTwo(String[] names) {
return Stream
.of(names)
.zipWithIndex()
.filter(tuple -> tuple._2 % 2 == 1)
.map(tuple -> tuple._1)
.toJavaList();
}
Мы можем проверить этот пример с помощью следующего метода:
@Test
public void whenCalled_thenReturnListOfOddStringsVersionTwo() {
String[] names
= {"Afrim", "Bashkim", "Besim", "Lulzim", "Durim", "Shpetim"};
List expectedResult
= Arrays.asList("Bashkim", "Lulzim", "Shpetim");
List actualResult
= StreamIndices.getOddIndexedStringsVersionTwo(names);
assertEquals(expectedResult, actualResult);
}
Если вы хотите узнать больше о Vavr,check this article.
6. Заключение
В этом быстром уроке мы увидели четыре подхода к тому, как перебирать потоки, используя индексы. Потоки привлекли большое внимание, и может быть полезна возможность их перебирать с помощью индексов.
В Java 8 Streams включено множество функций, некоторые из которых уже включены вexample.
Код для всех описанных здесь примеров и многое другое можно найти вover on GitHub.