【问题标题】:How to merge two Maps <String, LocalDateTime> and calculate difference between values in nanoseconds如何合并两个地图 <String, LocalDateTime> 并以纳秒为单位计算值之间的差异
【发布时间】:2020-01-28 08:50:39
【问题描述】:

每个人。 我在尝试合并两个地图Map&lt;String, LocalDateTime&gt; 时遇到了问题。 IDE 显示编译错误:

不能从静态上下文中引用非静态方法

问题是我需要将它们合并到一个具有不同参数作为值的新值中,在这种情况下,我需要计算第一张地图的 LocalDateTime 和第二张地图的 LocalDateTime 之间的差异,因此结果应该是Map&lt;String, Long&gt;

Map<String, Long> result = Stream.concat(logStartTimeMap.entrySet().stream(), logEndTimeMap.entrySet().stream())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (value1, value2) -> new Long(ChronoUnit.NANOS.between(value1,value2))));

我在 Map.Entry::getKey、Map.Entry::getValue 行中遇到错误。

另一个在ChronoUnit.NANOS.between(value1,value2) 行中,因为 IDE 认为 value1 和 value2 是 Object 类型而不是 Temporal。这很奇怪,因为之前我在结果 Map 中选择了不正确的参数类型时遇到了这个错误。不过这里没关系,ChronoUnit.NANOS.between(value1,value2) 返回 Long,Map 结果有 Long 作为参数。

【问题讨论】:

  • 如果另一张地图中不存在该键怎么办?那么如何计算差异呢?两张地图中的键是否相同?
  • 错误很明显。您不能将 LocalDateTimeLong 差异都作为地图中的值。 value 和 mergeFunction 应该相互符合,并且在您的情况下该条件不成立。
  • 您能否给我一个提示,如何让它们相互遵守?
  • 在不知道上述问题的答案的情况下,如何给您提示?
  • 我在两张地图中都有相同的键。数学键必须在第二张地图中。这样就消除了没有匹配键的情况

标签: java lambda collections java-8 java-stream


【解决方案1】:

我认为没有办法通过将两个地图合并到一个流中来做到这一点。

mergeFunction(Collectors.toMap 的第三个参数)必须是 BinaryOperator&lt;U&gt;。这意味着类似于 (U, U) -> U。但在您的代码中,它需要两个 LocalDateTime 类型的参数并返回一个 Long

你可以用这样的流来做到这一点:

Map<String, Long> result = logStartTimeMap.entrySet().stream()
      .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), ChronoUnit.NANOS.between(e.getValue(), logEndTimeMap.get(e.getKey()))))
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

【讨论】:

    【解决方案2】:

    您使用Collectors.toMap 的方式意味着您正在尝试返回Map&lt;String, LocalDateTime&gt;。那是因为Map.Entry::getKey 返回一个StringMap.Entry::getValue 返回一个LocalDateTime。然后在您的合并函数中,您尝试返回与通用签名不匹配的Long

    相反,您可以执行以下操作:

    Map<String, LocalDateTime> map1 = ...;
    Map<String, LocalDateTime> map2 = ...;
    
    Map<String, Duration> result = map1.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            entry -> Duration.between(entry.getValue(), map2.get(entry.getKey()))
    ));
    

    上面计算了一个Duration,它为您提供了比只有纳秒更多的灵活性,但您显然可以更改它以满足您的需求:

    Map<String, LocalDateTime> map1 = ...;
    Map<String, LocalDateTime> map2 = ...;
    
    Map<String, Long> result = map1.entrySet().stream().collect(Collectors.toMap(
            Map.Entry::getKey,
            entry -> entry.getValue().until(map2.get(entry.getKey()), ChronoUnit.NANOS)
    ));
    

    请注意,以上两个示例都假定map1 的密钥集是map2 的密钥集的子集。在comment 你说:

    我在两张地图中都有相同的键。数学键必须在第二张地图中。这样就消除了没有匹配键的情况

    这意味着假设是有效的。但是,如果该假设不正确,您需要做的就是添加一个过滤操作,在其中排除 map1 的任何条目,其密钥不存在于 map2 中。 Ravindra 在his answer 中展示了一个这样的例子。

    【讨论】:

      猜你喜欢
      • 2021-08-12
      • 1970-01-01
      • 2021-11-14
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2020-09-29
      • 1970-01-01
      相关资源
      最近更新 更多