【问题标题】:Filter operation via Stream and maintain as map instead of Stream通过 Stream 过滤操作并维护为 map 而不是 Stream
【发布时间】:2021-08-11 16:59:21
【问题描述】:

我目前正在从外部 api 调用中获取地图数据。
我想确保数据不为空或不为空,并对其执行一组操作
通过过滤到地图中的特定键并将结果捕获到另一个对象中。

密钥本身以逗号分隔。

地图中的示例键/值。

"key1,key2,key3,id100" : {
     "val1: "",
     "val2: "",
     "val3: "",
     ... others
}

我正在过滤以捕获此键下的所有值(因此数据 cal1、val2、val3 等) 然后执行一些操作。

但是当我执行如图所示的过滤器时,我最终得到了一个流。

因此,我最终得到的不仅仅是 Map,而是 Stream>

尝试过平面图并出现以下错误:

不存在类型变量 U 的实例,因此 Stream> 符合 Optional

如何将其从 Stream 转换回 Map 或更好的过滤方式?谢谢。

本可以通过没有 Streams 的 for 循环完成此操作,但尝试查看如何
我可以在 Stream 实现中实现这一点,因此无需寻找 for 循环解决方案。请指教。谢谢。

private NewObject get() {

    Map<String, Object> data = // data filled in by an external rest call;

    return Optional.ofNullable(data)

        // using flatmap here throws above error
        .map(Map::entrySet)
        .map(entries -> entries.stream()
                .filter(entry -> entry.getKey().contains("id100))

        // I wish to carry on further operations from here by using the filtered map. 
        // having issues cos capturedData is a Stream 

        // even if using flatmap at this stage, capturedData is still a Stream.
        // wanting to do the following but can't due to it being a Stream and not a map 
        ).map(capturedData -> {
            Map<String, Object> at = (Map<String, Object>) capturedData;

            NewObject newObject = new NewObject();
            newObject.setName((String) at.get("val1"));

            return newObject;

        }).orElse(null);
}

【问题讨论】:

  • 老实说,我只想说if (data == null) { return null; } 而不是尝试管道/嵌套主要逻辑。
  • @chrylis-cautiouslyoptimistic- 很公平。但是如果不为空,仍然想流式传输它。
  • 当键中有多个带有子字符串id100 的条目时,您如何处理?返回NewObjects 的列表?
  • @user7 基于与永远不会发生的外部提供商的合同。

标签: java java-8


【解决方案1】:

使用map 构造NewObject 并使用findFirst 获取第一个值(根据您的评论,只有一个条目的键具有子字符串id100)。最后用flatMap解开Optional&lt;NewObject&gt;

return Optional.ofNullable(data)
    .map(Map::entrySet)
    .flatMap(entries -> entries.stream()
            .filter(entry -> entry.getKey().contains("id100"))
            .map(entry -> {
                NewObject newObject = new NewObject();
                Map<String, String> nestedMap = (Map<String, String>) entry.getValue();
                newObject.setName(nestedMap.get("val1"));
                return newObject;
            })
            .findFirst())
    .orElse(null);

【讨论】:

  • 你是想把 findFirst() 放在 map(entry... 上面还是故意的?
【解决方案2】:

下面的代码过滤data 中的条目集,在执行下一组操作之前将其收集到一个集合中。使用findFirst 以便只处理一个条目。

Optional.ofNullable(data)
                .map(Map::entrySet)
                .map(entries -> 
                      entries
                        .stream()
                        .filter(e -> e.getKey().contains("id1000")).collect(Collectors.toSet()))
                .stream()
                .findFirst()
                .map(capturedData -> {
                    Map<String, Object> map = (Map<String, Object>) capturedData;
                    NewObject newObject = new NewObject();
                    newObject.setName((String) at.get("val1"));
                    return newObject;
                })
                .orElse(null);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-14
    • 2021-03-16
    • 2020-12-16
    • 1970-01-01
    • 2020-10-10
    • 2011-12-21
    • 2021-01-17
    • 2023-04-08
    相关资源
    最近更新 更多