Java8中类似Ruby的each_with_index方法的等效方法是什么?

6

我想知道是否有一些流操作可以像在Ruby中的each_with_index一样做。

each_with_index循环遍历值及其索引。

5个回答

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));

2
您可以在Eclipse Collections(以前称为GS Collections)中使用forEachWithIndex()
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);

如果您无法将您的`Collection`转换为GS Collections类型,则可以使用其中一个适配器,例如`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 的提交者。

2
您可以将其“减少”。
<T> void forEachIndexed(Stream<T> stream, BiConsumer<Integer, T> consumer) {
    stream.reduce(0, (index, t) -> {
        consumer.accept(index, t);
        return index + 1;
    }, Integer::max);
}

this way:

List<Integer> ints = Arrays.asList(1, 2, 4, 6, 8, 16, 32);

forEachIndexed(ints.stream(), (idx, el) -> {
     System.out.println(idx + ": " + el);
});

1
使用实用程序库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")));

1
使用流reduce操作和累加器(第二个参数)进行替代,以便产生副作用。如果您不需要reduce操作的结果,则第三个参数可以是任何函数。
 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);

注:虽然可能可以使用,但我个人不满意滥用reduce函数。 :)


我也是 :), 而且看起来很复杂! - Muhammad Hewedy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接