【问题标题】:Java Stream multi list iterationJava Stream 多列表迭代
【发布时间】:2016-07-02 12:04:14
【问题描述】:

我有 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 等所有方法都感到困惑。我不确定什么时候使用。

【问题讨论】:

  • 可以把所有的Foo对象放到一个map中,ID为key,然后通过ID获取Foo对象

标签: java list java-8 iteration java-stream


【解决方案1】:

直接的方法就是您在帖子中的内容:循环遍历 id,选择第一个具有该 id 的 Foo,如果找到,将其收集到 List。放入代码中,它将如下所示:每个 id 都映射到相应的 Foo,通过在具有该 id 的 foo 上调用 findFirst() 找到。这将返回一个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 并过滤掉 null 元素,这意味着没有找到 Foo


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

【讨论】:

  • 完美。这就是我要的。我意识到我在原始帖子中并没有完全代表我的场景。我的实际情况是有 2 个 Foo 对象列表,但第一个列表只有 Foo 对象和 Ids,而另一个列表有完整的 Foo 对象和其他成员变量的值。我想比较它们并检索完整的 foo 对象。您的第一个解决方案完美运行!但我无法让第二个在我的场景中工作
  • @Richard 在第二个 sn-p 中,如果你没有 id 列表而是部分 Foo 列表,你首先需要将每个 Foo 映射到它的 id,一些喜欢myPartialFoos.stream().map(Foo::getId).map(map::get) ...
  • 再次完美。感谢您的所有意见!
  • 在第一个sn-p中,可以将.map(...findFirst()).filter(Optional::isPresent).map(Optional::get)替换成.flatMap(...limit(1))
【解决方案2】:

我会这样实现它:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 2012-05-12
    相关资源
    最近更新 更多