Gen*_*han 9 java lambda java-8 java-stream
我有以下课程:
public class Item {
int id;
String name;
// few other fields, contructor, getters and setters
}
Run Code Online (Sandbox Code Playgroud)
我有一个项目清单.我想迭代列表并找到具有特定id的实例.我正试图通过溪流来做.
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--;
}
}
Run Code Online (Sandbox Code Playgroud)
这是迭代列表并获得我需要的元素的最佳方法吗?另外,我在id的过滤行上得到一个错误,它表示lambda表达式中使用的变量必须是final或者有效的final.也许我可以在while循环中定义id,这应该摆脱异常.谢谢.
Bye*_*Bye 10
您可以尝试使用以下内容:
ids.forEach(id ->
list.stream()
.filter(p -> p.getId() == id)
.findFirst()
.ifPresent(p -> {
// do stuff here
});
);
Run Code Online (Sandbox Code Playgroud)
这里的可选显示您的过滤器方法可以返回空流,因此如果您调用findFirst,它可以找到一个或零个元素.
如果您有很多要搜索的ID,建议使用一次性解决方案,而不是对每个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
});
}
Run Code Online (Sandbox Code Playgroud)
第一个语句只是从ids列表中创建一个映射,将每个搜索ID映射为空Optional.
第二个语句遍历项目使用forEach和为每个项目,它检查是否有从其id到空的映射Optional,并将替换它与Optional封装项目,如果有这样的映射,所有在一个操作,computeIfPresent.
最后一个for循环在ids列表上向后迭代,因为您希望按顺序处理它们并在非空的情况下执行操作Optional.由于地图是使用列表中找到的所有ID初始化的,get因此永远不会返回,如果在列表中找不到id,则null返回空.Optionalitems
这样一来,假设Map的查找具有O(1)时间复杂度,这是典型的实现的情况下,净时间复杂度从变化O(m×n)到O(m+n)...