是否有一种简洁的方法在流上迭代,同时访问流中的索引?

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

List<String> nameList;
Stream<Integer> indices = intRange(1, names.length).boxed();
nameList = zip(indices, stream(names), SimpleEntry::new)
        .filter(e -> e.getValue().length() <= e.getKey())
        .map(Entry::getValue)
        .collect(toList());

与这里给出的LINQ示例相比,这似乎相当令人失望

string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();

有更简洁的方式吗?

此外,似乎拉链已经移动或被拆除…


当前回答

下面是标准Java的解决方案:

在线解决方案:

Arrays.stream("zero,one,two,three,four".split(","))
        .map(new Function<String, Map.Entry<Integer, String>>() {
            int index;

            @Override
            public Map.Entry<Integer, String> apply(String s) {
                return Map.entry(index++, s);
            }
        })
        .forEach(System.out::println);

更可读的解决方案与实用方法:

static <T> Function<T, Map.Entry<Integer, T>> mapWithIntIndex() {
    return new Function<T, Map.Entry<Integer, T>>() {
        int index;

        @Override
        public Map.Entry<Integer, T> apply(T t) {
            return Map.entry(index++, t);
        }
    };
}

...
Arrays.stream("zero,one,two,three,four".split(","))
        .map(mapWithIntIndex())
        .forEach(System.out::println);

其他回答

你可以使用IntStream.iterate()来获取索引:

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList = IntStream.iterate(0, i -> i < names.length, i -> i + 1)
        .filter(i -> names[i].length() <= i)
        .mapToObj(i -> names[i])
        .collect(Collectors.toList());

这只适用于Java 9以上的Java 8,你可以使用这个:

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList = IntStream.iterate(0, i -> i + 1)
        .limit(names.length)
        .filter(i -> names[i].length() <= i)
        .mapToObj(i -> names[i])
        .collect(Collectors.toList());
String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
String completeString
         =  IntStream.range(0,namesArray.length)
           .mapToObj(i -> namesArray[i]) // Converting each array element into Object
           .map(String::valueOf) // Converting object to String again
           .collect(Collectors.joining(",")); // getting a Concat String of all values
        System.out.println(completeString);

山姆,帕梅拉,戴夫,帕斯卡,埃里克

String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

IntStream.range(0,namesArray.length)
               .mapToObj(i -> namesArray[i]) // Converting each array element into Object
               .map(String::valueOf) // Converting object to String again
               .forEach(s -> {
                //You can do various operation on each element here
                System.out.println(s);
               }); // getting a Concat String of all 

收集清单:

String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
 List<String> namesList
                =  IntStream.range(0,namesArray.length)
                .mapToObj(i -> namesArray[i]) // Converting each array element into Object
                .map(String::valueOf) // Converting object to String again
                .collect(Collectors.toList()); // collecting elements in List
        System.out.println(listWithIndex);

下面是标准Java的解决方案:

在线解决方案:

Arrays.stream("zero,one,two,three,four".split(","))
        .map(new Function<String, Map.Entry<Integer, String>>() {
            int index;

            @Override
            public Map.Entry<Integer, String> apply(String s) {
                return Map.entry(index++, s);
            }
        })
        .forEach(System.out::println);

更可读的解决方案与实用方法:

static <T> Function<T, Map.Entry<Integer, T>> mapWithIntIndex() {
    return new Function<T, Map.Entry<Integer, T>>() {
        int index;

        @Override
        public Map.Entry<Integer, T> apply(T t) {
            return Map.entry(index++, t);
        }
    };
}

...
Arrays.stream("zero,one,two,three,four".split(","))
        .map(mapWithIntIndex())
        .forEach(System.out::println);

如果你碰巧使用Vavr(以前称为Javaslang),你可以利用专用的方法:

Stream.of("A", "B", "C")
  .zipWithIndex();

如果我们打印出内容,我们会看到一些有趣的东西:

Stream((A, 0), ?)

这是因为流是懒惰的,我们不知道流中的下一项。

这里是常用的算盘代码

Stream.of(names).indexed()
      .filter(e -> e.value().length() <= e.index())
      .map(Indexed::value).toList();

披露:我是abacus-common的开发者。