【问题标题】:Java Map Lambda ExceptionJava 映射 Lambda 异常
【发布时间】:2016-08-11 03:16:11
【问题描述】:

我有一个映射列表,其中包含映射到字符串值的某些键。

类似List<Map<String,String>> aMapList;

目标:流过此地图列表并收集所有地图中单个键的值。

我是怎么做的 ->

key = "somekey";
aMapList.stream().map(a -> a.get(key)).collect(Collectors.averagingInt());

问题: 如果没有这样的密钥,我会得到异常由于 a.get(key)!因为平均这将给出一个空值。如何检查或使 lambda 忽略任何此类映射并继续前进。

我知道我可以在a -> a.contains(key) 上添加一个过滤器,然后继续。 编辑:我还可以添加更多过滤器或在一个过滤器上简单地检查多个条件。 可能的解决方案:

    aMapList.stream().filter(a -> a.contains(key)).
         map(a -> a.get(key)).collect(Collectors.averagingInt());

这可以变得更漂亮吗? 不要停止操作,而是跳过它们? 是否有一些更通用的方法可以跳过异常或空值。 例如。我们可以扩展 lambda 并放置一个 try-catch 块,但我仍然需要返回一些东西,如果我想做相当于“继续”的操作。

例如。

(a -> {return a.get(key) }).

可以扩展为-->

(a -> {try{return a.get(key)} 
catch(Exception e){return null} }).

上面仍然返回一个null,而不是只是跳过。

我选择了给出两个选项的最佳答案,但我没有发现其中任何一个更漂亮。链接过滤器似乎是解决此问题的方法。

【问题讨论】:

  • 为什么会出现异常?你不应该得到null吗?
  • 我知道一种解决方案。我只是问我是否可以用更短的方式做到这一点。太多的过滤器看起来很难看,让人困惑。
  • @cricket_007,因为以后的操作会抛出异常。我会得到 null,但稍后它会中断并抛出异常。
  • 然后您需要在某个时候过滤空值或在地图中忽略它们。基本上,似乎没有比你所拥有的“更简单”的方法了
  • 根据@DannyChen 的说法,contains(key) 返回 true 并不能保证 get(key) 将返回非空值。对于某些Map 实现,您可以输入空值。

标签: java lambda java-stream


【解决方案1】:

Optional 包装结果怎么样:

List<Optional<String>> values = aMapList.stream()
            .map(a -> Optional.ofNullable(a.get(key)))
            .collect(Collectors.toList());

稍后的代码会知道可能存在空元素。


您提出的解决方案对于允许 null 值的地图存在潜在错误。例如:

Map<String, String> aMap = new HashMap<>();
aMap.put("somekey", null);

aMapList.add(aMap);

aMapList.straem()
    .filter(a -> a.contains("somekey")) // true returned for contains
    .map(a -> a.get("somekey")) // null returned for get
    .collect(Collectors.toList());

【讨论】:

  • 我忘了在过滤器中添加,我也可以过滤空值。对于那个很抱歉。我的意思是,我可以通过链接过滤器过滤掉任何数量的东西,从而过滤掉空值。我想知道是否有一种方法可以执行“try{},catch{ignore}”之类的操作。如果忽略任何此类情况,我们将移至列表中。
【解决方案2】:

根据Map documentation,以及您在问题下的评论,您实际上并没有从a.get(key) 获得例外。相反,该表达式会产生一个空值,并且稍后当您遇到这些空值时会遇到问题。因此,只需立即过滤掉这些空值就可以了:

aMapList.stream()
    .map(a -> a.get(key))
    .filter(v -> v != null)
    .collect(Collectors.toList());

这比您问题中的解决方法更漂亮、更简单且性能更好。

我应该提一下,在处理 null 值时,我通常更喜欢 Optional&lt;&gt; 类型,但这种过滤方法在这种情况下效果更好,因为您明确表示要忽略映射列表中不存在键的元素.

【讨论】:

  • 应该是v != null
  • @LukeLee v != null 也有一个潜在的错误,当地图有一个带有 null 值的键时。
  • 目前比较担心常见情况下得不到正确的结果。
  • @LukeLee:对。错了。 :-) @Danny Chen,我假设 OP 已经检查了 key 在此语句之外的空值。
  • 是的。那可行。我的实际 lambda 比这个大一点,我稍后会做一些像 count() 这样的事情。我没有在这里写它,因为它没有任何用途。
【解决方案3】:

我能想到的最简单的是:

aMapList.stream()
        .filter(map -> map.containsKey(key))
        .map(map -> map.get(key))
        .collect(Collectors.toList());

通过以这种方式格式化 lambda,可以更轻松地查看代码处理的不同步骤。

【讨论】:

  • 我已经建议这是一个可能的解决方案。我想问的是,即使出现异常,我的 lambda 是否有办法继续工作。
  • 我提出了一种格式,使 lambda 更易于阅读和理解。我认为这个 lambda(正如您所说的与您的基本相同)是最简单的解决方案。
【解决方案4】:

虽然我认为这不是一个更漂亮的方法,但您可以这样做:

aMapList.stream().map(a -> a.containsKey(key) ? a.get(key) : null).collect(Collectors.toList());

【讨论】:

  • a.get(key) 返回 null,因此检查它是否包含似乎毫无意义
  • 除了板球所说的,我宁愿添加另一个过滤器:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多