ストリーム内のインデックスにアクセスしながらストリームを反復処理する簡潔な方法はありますか?
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();
もっと簡潔な方法はありますか?
さらに、ジッパーが移動したか削除されたようです...
ベストアンサー1
最もクリーンな方法は、インデックスのストリームから開始することです。
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());
結果のリストには「Erik」のみが含まれます。
for ループに慣れている場合にもっと馴染みのある代替案としては、次のような可変オブジェクトを使用してアドホック カウンターを維持することが挙げられます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());
後者の方法を並列ストリームで使用すると、アイテムが必ずしも「順番に」処理されないため、処理が失敗する可能性があることに注意してください。