【发布时间】:2019-06-05 08:00:53
【问题描述】:
如何在 Java 中使用 stream() 根据索引(位置)过滤列表中的元素?
我想过滤每三个元素(即List<String> 的索引 0、3、6、9、...)。
【问题讨论】:
-
你有没有尝试过?
-
到目前为止你有什么尝试?
标签: java java-stream
如何在 Java 中使用 stream() 根据索引(位置)过滤列表中的元素?
我想过滤每三个元素(即List<String> 的索引 0、3、6、9、...)。
【问题讨论】:
标签: java java-stream
从 Java 9 开始,您可以使用 IntStream.iterate() 来实现:
IntStream.iterate(0, i -> i < list.size(), i -> i + 3)
.mapToObj(list::get)
.forEach(System.out::println);
如果你使用的是 Java 8,你可以使用这个:
IntStream.iterate(0, i -> i + 3)
.limit(list.size() / 3)
.mapToObj(list::get)
.forEach(System.out::println);
编辑: 正如 Holger 在 cmets 中指出的那样,更有效的解决方案是:
IntStream.range(0, list.size() / 3)
.mapToObj(i -> list.get(i * 3))
.forEach(System.out::println);
【讨论】:
IntStream.range(0, list.size()/3).mapToObj(i -> list.get(i*3)) …
您必须使用 IntStream。
例如,以下将创建一个Stream,其中包含所有索引可被3整除的List元素:
List<String> yourList = ...
IntStream.range(0,yourList.size()) // IntStream of 0,1,2,3,...
.filter(i -> i % 3 == 0) // IntStream of 0,3,6,...
.mapToObj(yourList::get) // Stream<String> of yourList.get(0),yourList.get(3),...
...
【讨论】:
get 不能直接访问的任何列表(如LinkedList),这比在无聊的旧式中使用其迭代器循环遍历列表效率要低得多-老式的方式。但问题确实指定了流...(使用像 ArrayList 这样的直接访问列表,它只是效率较低,而不是显着效率降低。)
LinkedList。但是使用IntStream.range(0, list.size()/3).mapToObj(i -> list.get(i*3)) … 会更有效,因为它避免了执行涉及模运算的list.size() 条件,并使流能够利用已知大小,例如用于终端操作toArray、count 或并行流。这已经比基于 Iterator 的循环更有效,并且可以在内联后优化到与计数循环相同的性能。
List 接口的任何算法(获取ListIterator 除外)。如果没有更好的选择,您很少会找到LinkedList 的用例。这不是关于链表的概念,而是这个特定的实现类作为 Java 集合框架的成员。