使用 java 8 从特定键值的映射列表创建数组列表

Create arraylist from list of maps for certain key value with java 8

我有一个包含地图列表的对象。每张地图如下所示:

{
  id: "something",
  link: "someLink"
}

我正在尝试创建地图中所有 ID 的数组列表。我可以用一个简单的循环来做到这一点

 List<String> Ids = new ArrayList<>();
        
 List<Map<String, String>> maps = pojo.getMaps();
        
 for(Map<String, String> map: maps) {
       Ids.add(map.get("id"));
    }

但是这是如何使用 java 8 个流在一行中完成的?我从来没有在地图上使用过它,所以我迷路了。 我假设它会像这样,但老实说我不知道​​

List<String> ids = pojo.getMaps().stream().map(Map.Entry::  ???? ).collect(Collectors.toList())

您可以在循环中以相同的方式从地图中获取 id 的值。这里的.map() used to transform Map<String, String> to String 表示将Map transform to value of key id

List<String> ids = pojo.getMaps().stream()                 // Stream<Map<String, String>>
                                 .map(e -> e.get("id"))    // Stream<String> 
                                 .collect(Collectors.toList());

pojo.getMaps().stream()

到目前为止,还不错。您现在拥有 Map<String, String> 个对象流。我们只需要从中获取密钥。那么,给定一个奇怪的地图事物,我们如何将其转换为键值?

看起来微不足道map.get("id") 完成这项工作,不是吗?

所以让我们把它放在 lambda 中:

pojo.getMaps().stream().map(theMap -> theMap.get("id"))

现在我们有一个带有 id 的 Stream<String>

但是,请注意!

您从看起来像对象的地图对象开始这一事实是一种巨大的代码味道。您很可能应该返回项目中的几个步骤并修复它。你真的应该有一个 class 代表这个 link 概念:

@Value
public class Link {
    String id, link;
}

然后从那里开始:

listOfLinks.stream().map(Link::getId).distinct().collect(...);

注意:以上使用 Lombok's @Value.

功能只是一个工具

请注意,无需将代码重写为 'use java 8 features'。比较:

    var ids = pojo.getMaps().stream()
      .map(m -> m.get("id"))
      .collect(Collectors.toList());

与:

    var ids = new ArrayList<String>();
    for (var m : pojo.getMaps()) ids.add(m.get("id"));

代码量差不多。