繁体   English   中英

Java Stream 多列表迭代

[英]Java Stream multi list iteration

我有 2 个列表。 1 个列表包含 Id,另一个列表充满Foo对象,称为列表 A。 Foo类如下所示:

public class Foo {
    private String id;
    /* other member variables */

    Foo(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }
}

我有一个简单的 id 列表,如List<Integer> ,将其称为列表 B。我想要做的是一次迭代列表 B 一个元素,获取 id,将其与列表 A 进行比较,然后获取具有等效项的Foo对象id,然后将Foo对象添加到新列表,即列表 C。

我正在尝试连接流,但我是流的新手,并且我对mapfilterforEach等所有方法陷入了困境。 我不确定何时使用什么。

最简单的方法就是您在帖子中的内容:遍历 id,选择第一个具有该 id 的Foo ,如果找到,则将其收集到List 放入代码中,它看起来像下面这样:每个 id 都映射到相应的Foo ,通过在具有该 id 的 foo 上调用findFirst()找到该Foo 这将返回一个Optional被过滤掉它Foo不存在。

List<Integer> ids = Arrays.asList(1, 2, 3);
List<Foo> foos = Arrays.asList(new Foo("2"), new Foo("1"), new Foo("4"));

List<Foo> result =
    ids.stream()
       .map(id -> foos.stream().filter(foo -> foo.getId().equals(id.toString())).findFirst())
       .filter(Optional::isPresent)
       .map(Optional::get)
       .collect(Collectors.toList());

这种方法的一个大问题是您需要遍历foos列表,次数与要查找的 id 一样多。 一个更好的解决方案是首先创建一个查找Map ,其中每个 id 映射到Foo

Map<Integer, Foo> map = foos.stream().collect(Collectors.toMap(f -> Integer.valueOf(f.getId()), f -> f));

List<Foo> result = ids.stream().map(map::get).filter(Objects::nonNull).collect(Collectors.toList());

在这种情况下,我们查找Foo并过滤掉表示未找到Foo null元素。


另一种完全不同的方法不是遍历 id 并搜索Foo ,而是过滤具有包含在通缉列表中的 id 的Foo 方法的问题在于,它需要对输出列表进行排序,以便结果列表的顺序与 id 的顺序相匹配。

我会像这样实现它:

List<Foo> list = Arrays.asList(
    new Foo("abc"),
    new Foo("def"),
    new Foo("ghi")
);

List<String> ids = Arrays.asList("abc", "def", "xyz");

//Index Foo by ids
Map<String, Foo> map = list.stream()
  .collect(Collectors.toMap(Foo::getId, Function.identity()));

//Iterate on ids, find the corresponding elements in the map
List<Foo> result = ids.stream().map(map::get)
  .filter(Objects::nonNull) //Optional...
  .collect(Collectors.toList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM