Java流过滤特定索引的项目

Ved*_*nth 14 java java-8 java-stream

我正在寻找一种简洁的方法来过滤掉特定索引中List中的项目.我的示例输入如下所示:

List<Double> originalList = Arrays.asList(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0);
List<Integer> filterIndexes = Arrays.asList(2, 4, 6, 8);
Run Code Online (Sandbox Code Playgroud)

我想筛选出的索引项2,4,6,8.我有一个for循环跳过与索引匹配的项目,但我希望有一种简单的方法可以使用流来完成.最终结果如下:

List<Double> filteredList = Arrays.asList(0.0, 1.0, 3.0, 5.0, 7.0, 9.0, 10.0);
Run Code Online (Sandbox Code Playgroud)

Ale*_* C. 20

您可以生成一个IntStream模仿原始列表的索引,然后删除列表中的索引,然后将filteredIndexes这些索引映射到列表中的相应元素(更好的方法是HashSet<Integer>使用索引,因为它们是唯一的定义,这contains是一个恒定的时间操作).

List<Double> filteredList = 
    IntStream.range(0, originalList.size())
             .filter(i -> !filterIndexes.contains(i))
             .mapToObj(originalList::get)
             .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)


Tag*_*eev 5

如果filteredIndexes列表是预先排序的,则可以避免以这种方式检查每个元素:

List<Double> filteredList = IntStream.rangeClosed(0, filterIndexes.size())
    .mapToObj(idxPos -> idxPos == 0 
           ? originalList.subList(0, filterIndexes.get(idxPos)) 
           : idxPos == filterIndexes.size() 
           ? originalList.subList(filterIndexes.get(idxPos-1)+1, originalList.size()) 
           : originalList.subList(filterIndexes.get(idxPos-1)+1, filterIndexes.get(idxPos)))
    .flatMap(List::stream)
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

在这里,我们创建了许多子列表,其中包含过滤索引之间的所有元素,然后将它们展平为单个最终列表.对于大输入(例如一百万个数字),这个解决方案可能比@AlexisC提出的解决方案更快.