Gra*_*oss 361 java java-8 java-stream
有没有一种简洁的方法来迭代流,同时有权访问流中的索引?
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());
Run Code Online (Sandbox Code Playgroud)
与那里给出的LINQ示例相比,这似乎相当令人失望
string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();
Run Code Online (Sandbox Code Playgroud)
有更简洁的方法吗?
此外,看起来拉链已移动或被移除......
ass*_*ias 399
最简洁的方法是从一系列指数开始:
String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
IntStream.range(0, names.length)
.filter(i -> names[i].length() <= i)
.mapToObj(i -> names[i])
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
结果列表仅包含"Erik".
当您习惯于循环时,一种看起来更熟悉的替代方法是使用可变对象维护一个临时计数器,例如AtomicInteger:
String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
AtomicInteger index = new AtomicInteger();
List<String> list = Arrays.stream(names)
.filter(n -> n.length() <= index.incrementAndGet())
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
请注意,在并行流上使用后一种方法可能会中断,因为项目不会按顺序"按顺序"处理.
Stu*_*rks 66
Java 8流API缺少获取流元素索引的功能以及将流压缩在一起的功能.这是不幸的,因为它使某些应用程序(如LINQ挑战)比其他方式更难.
但是,通常有解决方法.通常,这可以通过用整数范围"驱动"流来完成,并利用原始元素通常在数组中或在索引可访问的集合中的事实.例如,挑战2问题可以通过这种方式解决:
String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList =
IntStream.range(0, names.length)
.filter(i -> names[i].length() <= i)
.mapToObj(i -> names[i])
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
如上所述,这利用了数据源(名称数组)可直接索引的事实.如果不是,这种技术将不起作用.
我承认这不符合挑战2的意图.尽管如此,它确实可以合理有效地解决问题.
编辑
我之前的代码示例用于flatMap融合过滤器和映射操作,但这很麻烦并且没有任何优势.我根据Holger的评论更新了示例.
num*_*ro6 39
自番石榴21,你可以使用
Streams.mapWithIndex()
Run Code Online (Sandbox Code Playgroud)
示例(来自官方文档):
Streams.mapWithIndex(
Stream.of("a", "b", "c"),
(str, index) -> str + ":" + index)
) // will return Stream.of("a:0", "b:1", "c:2")
Run Code Online (Sandbox Code Playgroud)
小智 25
我在我的项目中使用了以下解决方案.我认为它比使用可变对象或整数范围更好.
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static java.util.Objects.requireNonNull;
public class CollectionUtils {
private CollectionUtils() { }
/**
* Converts an {@link java.util.Iterator} to {@link java.util.stream.Stream}.
*/
public static <T> Stream<T> iterate(Iterator<? extends T> iterator) {
int characteristics = Spliterator.ORDERED | Spliterator.IMMUTABLE;
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, characteristics), false);
}
/**
* Zips the specified stream with its indices.
*/
public static <T> Stream<Map.Entry<Integer, T>> zipWithIndex(Stream<? extends T> stream) {
return iterate(new Iterator<Map.Entry<Integer, T>>() {
private final Iterator<? extends T> streamIterator = stream.iterator();
private int index = 0;
@Override
public boolean hasNext() {
return streamIterator.hasNext();
}
@Override
public Map.Entry<Integer, T> next() {
return new AbstractMap.SimpleImmutableEntry<>(index++, streamIterator.next());
}
});
}
/**
* Returns a stream consisting of the results of applying the given two-arguments function to the elements of this stream.
* The first argument of the function is the element index and the second one - the element value.
*/
public static <T, R> Stream<R> mapWithIndex(Stream<? extends T> stream, BiFunction<Integer, ? super T, ? extends R> mapper) {
return zipWithIndex(stream).map(entry -> mapper.apply(entry.getKey(), entry.getValue()));
}
public static void main(String[] args) {
String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
System.out.println("Test zipWithIndex");
zipWithIndex(Arrays.stream(names)).forEach(entry -> System.out.println(entry));
System.out.println();
System.out.println("Test mapWithIndex");
mapWithIndex(Arrays.stream(names), (Integer index, String name) -> index+"="+name).forEach((String s) -> System.out.println(s));
}
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*ean 13
除了protonpack之外,jOOλ的Seq提供了这个功能(并且通过扩展库构建在它上面就像独眼巨人反应一样,我是这个库的作者).
Seq.seq(Stream.of(names)).zipWithIndex()
.filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1)
.toList();
Run Code Online (Sandbox Code Playgroud)
Seq还支持Seq.of(名称),并将构建一个JDK Stream.
简单反应的等价物同样如此
LazyFutureStream.of(names)
.zipWithIndex()
.filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1)
.toList();
Run Code Online (Sandbox Code Playgroud)
简单反应版本更适合异步/并发处理.
Tag*_*eev 12
String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
EntryStream.of(names)
.filterKeyValue((idx, str) -> str.length() <= idx+1)
.values().toList();
Run Code Online (Sandbox Code Playgroud)
在这里,我们创建一个EntryStream<Integer, String>扩展Stream<Entry<Integer, String>>并添加一些特定的操作,如filterKeyValue或values.也使用toList()快捷方式.
如果您碰巧使用 Vavr(以前称为 Javaslang),您可以利用专用方法:
Stream.of("A", "B", "C")
.zipWithIndex();
Run Code Online (Sandbox Code Playgroud)
如果我们打印出内容,我们会看到一些有趣的东西:
Stream((A, 0), ?)
Run Code Online (Sandbox Code Playgroud)
这是因为Streams我们很懒,并且我们不知道流中的下一个项目。
在创建列表或数组的流(并且知道大小)后,在这里找到了解决方案。但是,如果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);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
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());
});
}
Run Code Online (Sandbox Code Playgroud)
Stream.of(names).indexed()\n .filter(e -> e.value().length() <= e.index())\n .map(Indexed::value).toList();\nRun Code Online (Sandbox Code Playgroud)\nDisclosure\xef\xbc\x9a 我是 abacus-common 的开发者。
\n有了清单,您可以尝试
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));
});
Run Code Online (Sandbox Code Playgroud)
输出:
0 => First
1 => Second
2 => Third
3 => Fourth
4 => Fifth
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
237340 次 |
| 最近记录: |