java 特定索引的Java流过滤项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36294051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:14:05  来源:igfitidea点击:

Java stream filter items of specific index

javajava-8java-stream

提问by Vedanth

I'm looking for a concise way to filter out items in a List at a particular index. My example input looks like this:

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

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);

I want to filter out items at index 2, 4, 6, 8. I have a for loop that skips items that match the index but I was hoping there would be an easy way of doing it using streams. The final result would look like that:

我想过滤掉 index 2, 4, 6, 处的项目8。我有一个 for 循环,它跳过与索引匹配的项目,但我希望有一种使用流的简单方法。最终结果如下所示:

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

回答by Alexis C.

You can generate an IntStreamto mimic the indices of the original list, then remove the ones that are in the filteredIndexeslist and then map those indices to their corresponding element in the list (a better way would be to have a HashSet<Integer>for indices since they are unique by definition so that containsis a constant time operation).

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

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

回答by Tagir Valeev

If your filteredIndexeslist is presorted, you can avoid checking every element in this way:

如果您的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());

Here we create a number of sublists which contain all the elements between the filtered indices, then just flatten them into the single final list. For big input (e.g. a million of numbers) this solution could be magnitudes faster than one proposed by @AlexisC.

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

回答by slartidan

If you sort your indexes descending, then you can use java.util.List.remove(int)to remove the items.

如果您对索引进行降序排序,则可以使用java.util.List.remove(int)删除项目。

List<Double> originalList = new ArrayList<>(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);

filterIndexes.stream()

    // remove higher indixes first, because each remove affects all indexes to the right
    .sorted(Comparator.reverseOrder())

    // make sure to use remove(int) not remove(Object) in java.util.List to use indexes
    .mapToInt(Integer::intValue)

    // remove each index
    .forEach(originalList::remove);

// print results
originalList.forEach(System.out::println);