Java8 эквивалент для ruby's each_with_index
Интересно, есть ли какая-нибудь потоковая операция, которая может сделать как each_with_index
в рубине.
куда each_with_index
перебирает значение, а также индекс значения.
5 ответов
Для этой цели нет потоковой операции. Но вы можете имитировать функциональность несколькими способами.
Индексная переменная: следующий подход прекрасно работает для последовательных потоков.
int[] index = { 0 };
stream.forEach(item -> System.out.printf("%s %d\n", item, index[0]++));
Внешняя итерация: следующий подход прекрасно работает для параллельных потоков, если исходная коллекция поддерживает произвольный доступ.
List<String> tokens = ...;
IntStream.range(0, tokens.size()).forEach(
index -> System.out.printf("%s %d\n", tokens.get(index), index));
Ты можешь использовать forEachWithIndex()
in http://www.eclipse.org/collections/ (formerly GS Collections).
MutableList<Integer> elements = FastList.newList();
IntArrayList indexes = new IntArrayList();
MutableList<Integer> collection = this.newWith(1, 2, 3, 4);
collection.forEachWithIndex((Integer object, int index) -> {
elements.add(object);
indexes.add(index);
});
Assert.assertEquals(FastList.newListWith(1, 2, 3, 4), elements);
Assert.assertEquals(IntArrayList.newListWith(0, 1, 2, 3), indexes);
If you cannot convert your Collection
to a GS Collections type, you can use one of the adapters, like ListAdapter
,
List<Integer> list = Arrays.asList(1, 2, 3, 4);
ListIterable<Integer> collection = ListAdapter.adapt(list);
collection.forEachWithIndex((object, index) -> {
elements.add(object);
indexes.add(index);
});
Примечание: я являюсь коммиттером для Eclipse Collections.
Вы можете reduce
Это
<T> void forEachIndexed(Stream<T> stream, BiConsumer<Integer, T> consumer) {
stream.reduce(0, (index, t) -> {
consumer.accept(index, t);
return index + 1;
}, Integer::max);
}
сюда:
List<Integer> ints = Arrays.asList(1, 2, 4, 6, 8, 16, 32);
forEachIndexed(ints.stream(), (idx, el) -> {
System.out.println(idx + ": " + el);
});
Альтернатива с потоком уменьшить работу с аккумулятором (2-й параметр) для побочного эффекта. Третьим параметром может быть любая функция, если вам не нужен результат операции сокращения.
List<String> tokens = Arrays.asList("A", "B", "C", "D");
tokens.stream().reduce(1, (i, str) -> {
System.out.printf("%s %d\n", str, i);
return i + 1;
}, Integer::max);
PS: Хотя это возможно, меня лично не устраивает злоупотребление понижающей функцией.:)
Это легко сделать с помощью служебной библиотеки protonpack: https://github.com/poetix/protonpack
Stream<String> source = Stream.of("Foo", "Bar", "Baz");
List<Indexed<String>> zipped = StreamUtils.zipWithIndex(source).collect(Collectors.toList());
assertThat(zipped, contains(
Indexed.index(0, "Foo"),
Indexed.index(1, "Bar"),
Indexed.index(2, "Baz")));