是否有一种简洁的方法在流上迭代,同时访问流中的索引?
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();
有更简洁的方式吗?
此外,似乎拉链已经移动或被拆除…
我在这里找到了解决方案,当流创建的列表或数组(你知道的大小)。但是如果Stream的大小未知呢?在这种情况下,试试这个变体:
public class WithIndex<T> {
private int index;
private T value;
WithIndex(int index, T value) {
this.index = index;
this.value = value;
}
public int index() {
return index;
}
public T value() {
return value;
}
@Override
public String toString() {
return value + "(" + index + ")";
}
public static <T> Function<T, WithIndex<T>> indexed() {
return new Function<T, WithIndex<T>>() {
int index = 0;
@Override
public WithIndex<T> apply(T t) {
return new WithIndex<>(index++, t);
}
};
}
}
用法:
public static void main(String[] args) {
Stream<String> stream = Stream.of("a", "b", "c", "d", "e");
stream.map(WithIndex.indexed()).forEachOrdered(e -> {
System.out.println(e.index() + " -> " + e.value());
});
}
为了完整起见,这里是涉及我的StreamEx库的解决方案:
String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
EntryStream.of(names)
.filterKeyValue((idx, str) -> str.length() <= idx+1)
.values().toList();
这里我们创建了一个EntryStream<Integer, String>,它扩展了Stream<Entry<Integer, String>>,并添加了一些特定的操作,如filterKeyValue或values。也使用了toList()快捷方式。
使用列表,你可以尝试一下
List<String> strings = new ArrayList<>(Arrays.asList("First", "Second", "Third", "Fourth", "Fifth")); // An example list of Strings
strings.stream() // Turn the list into a Stream
.collect(HashMap::new, (h, o) -> h.put(h.size(), o), (h, o) -> {}) // Create a map of the index to the object
.forEach((i, o) -> { // Now we can use a BiConsumer forEach!
System.out.println(String.format("%d => %s", i, o));
});
输出:
0 => First
1 => Second
2 => Third
3 => Fourth
4 => Fifth
下面是标准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);
我在这里找到了解决方案,当流创建的列表或数组(你知道的大小)。但是如果Stream的大小未知呢?在这种情况下,试试这个变体:
public class WithIndex<T> {
private int index;
private T value;
WithIndex(int index, T value) {
this.index = index;
this.value = value;
}
public int index() {
return index;
}
public T value() {
return value;
}
@Override
public String toString() {
return value + "(" + index + ")";
}
public static <T> Function<T, WithIndex<T>> indexed() {
return new Function<T, WithIndex<T>>() {
int index = 0;
@Override
public WithIndex<T> apply(T t) {
return new WithIndex<>(index++, t);
}
};
}
}
用法:
public static void main(String[] args) {
Stream<String> stream = Stream.of("a", "b", "c", "d", "e");
stream.map(WithIndex.indexed()).forEachOrdered(e -> {
System.out.println(e.index() + " -> " + e.value());
});
}