Java 8 Stream在列表中查找元素 [英] Java 8 Stream to find element in list

查看:693
本文介绍了Java 8 Stream在列表中查找元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆