Java 8 Stream在列表中查找元素 [英] Java 8 Stream to find element in list
问题描述
我有以下课程:
public class Item {
int id;
String name;
// few other fields, contructor, getters and setters
}
我有一个物品清单.我想遍历列表并找到具有特定ID的实例.我正在尝试通过流来做到这一点.
I have a list of Items. I want to iterate through the list and find the instance which has a particular id. I'm trying to do it through streams.
public void foobar() {
List<Item> items = getItemList();
List<Integer> ids = getIdsToLookup();
int id, i = ids.size() - 1;
while (i >= 0) {
id = ids.get(i);
Optional<Item> item = items
.stream()
.filter(a -> a.getId() == id)
.findFirst();
// do stuff
i--;
}
}
这是遍历列表并获取所需元素的最佳方法吗?另外,我在id的过滤器行上收到一条错误,该错误说在lambda表达式中使用的变量必须是final或有效的final.也许我可以在while循环中定义id,这应该摆脱异常.谢谢.
Is this the best way to iterate over the list and get the element I need? Also, I get an error on the filter line for id which says variables used in lambda expressions must be final or effectively final. Maybe I can define id inside the while loop, that should get rid of the exception. Thanks.
推荐答案
如果要搜索的ID过多,建议使用一次通过的解决方案,而不是对每个ID进行线性搜索:
If you have lots of ids to search, it's recommended to use a solution which does it in a single pass rather than doing a linear search for each id:
Map<Integer,Optional<Item>> map=ids.stream()
.collect(Collectors.toMap(id -> id, id -> Optional.empty()));
items.forEach(item ->
map.computeIfPresent(item.getId(), (i,o)->o.isPresent()? o: Optional.of(item)));
for(ListIterator<Integer> it=ids.listIterator(ids.size()); it.hasPrevious();) {
map.get(it.previous()).ifPresent(item -> {
// do stuff
});
}
第一条语句只是在id列表之外创建了一个映射,将每个搜索id映射到一个空的Optional
.
The first statement simply create a map out of the ids list, mapping each search id to an empty Optional
.
第二条语句使用forEach
遍历所有项目,对于每个项目,它检查是否存在从其ID到空的Optional
的映射,如果存在,则将其替换为封装该项目的Optional
这样的映射,只需一次操作computeIfPresent
.
The second statement iterates over the items using forEach
and for each item, it checks whether there’s a mapping from its id to an empty Optional
and will replace it with an Optional
encapsulating the item, if there is such a mapping, all in one operation, computeIfPresent
.
最后一个for
循环在ids
列表上向后迭代,因为您希望以此顺序处理它们,并在有非空Optional
时执行操作.由于映射是使用列表中找到的所有ID初始化的,因此get
将永远不会返回null
,如果在items
列表中未找到ID,它将返回一个空的Optional
.
The last for
loop iterates backwards over the ids
list, as you wished to process them in that order and perform the action if there’s a non-empty Optional
. Since the map was initialized with all ids found in the list, get
will never return null
, it will return an empty Optional
, if the id was not found in the items
list.
这样,假设Map
的查找具有O(1)
时间复杂度(在典型的实现中就是这种情况),则净时间复杂度从O(m×n)
更改为O(m+n)
…
That way, assuming that the Map
’s lookup has O(1)
time complexity, which is the case in typical implementations, the net time complexity changed from O(m×n)
to O(m+n)
…
这篇关于Java 8 Stream在列表中查找元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!