【问题标题】:How to filter the Map with Stream when null occurs? [duplicate]发生 null 时如何使用 Stream 过滤 Map? [复制]
【发布时间】:2017-11-27 08:25:54
【问题描述】:

我想通过Stream 过滤Map 中的一些值。让我们看一个简单的例子,我想提取带有键的条目,例如大于 2。

这是我使用的代码:

Map<Integer, String> map = new HashMap<>(); 
map.put(1, "one"); 
map.put(2, "two"); 
map.put(3, "three"); 
map.put(4, "four"); 

Map<Integer, String> map2 = map.entrySet().stream()
    .filter(e -> e.getKey() > 2)
    .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));

System.out.println(map2.toString());

结果正确:

{3=三个,4=四个}

当我决定将String值设为null时,这是合法的,这是抛出:

线程“主”java.lang.NullPointerException 中的异常

下面是代码的延续:

map.put(5, null);
map.put(6, "six");

Map<Integer, String> map3 = map.entrySet().stream()
    .filter(e -> e.getKey() > 2)
    .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));

System.out.println(map3.toString());

我希望结果:

{3=3, 4=4, 5=null, 6=6}

好吧,当我将过滤器的Predicate 中的条件更改为e -&gt; e.getKey() &lt; 2 时,它会起作用,因为null 值不受影响。如何使用Stream 处理这个问题? null 值可能有意出现在任何地方。我不想使用 for 循环。 Stream 架构不应该更“空安全”吗?

问题How should we manage jdk8 stream for null values 处理不同的问题。我不想使用.filter(Objects::nonNull),因为我需要保留null 的值。


请不要将其标记为与著名的What is a NullPointerException and how do I fix it 重复。我很清楚这一点,我使用Stream 询问解决方案,它不像for-loop 那样低级。这种行为非常限制我。

【问题讨论】:

  • herehere
  • @NikolasCharalambidis 与当前的toMap 实现你不能放空值。您必须创建自己的 collector - 这在链接问题的答案之一中有所描述
  • @NikolasCharalambidis 链接的问题(连同他们的答案)怎么没有回答您的问题?
  • 除非你没有告诉我们什么,否则它就是重复的。确切的答案是:Map&lt;Integer, String&gt; map3 = map.entrySet().stream().filter(e -&gt; e.getKey() &gt; 2).collect(HashMap::new, (map, entry) -&gt; map.put(entry.getKey(), entry.getValue()), HashMap::putAll); 这能满足您的需求吗?
  • 因为 链接问题之一中的答案......但这应该没关系 - 你找到你的解决方案很好

标签: java dictionary nullpointerexception java-8 java-stream


【解决方案1】:

Optional 是一个容器对象,用于包含非空对象。可选对象用于表示没有值的空值。

你可以这样做:

Map<Integer, Optional<String>> map = new HashMap<>(); 

//Optional.ofNullable - allows passed parameter to be null.
map.put(1, Optional.ofNullable("one")); 
map.put(2, Optional.ofNullable("two")); 
map.put(3, Optional.ofNullable(null)); 
map.put(4, Optional.ofNullable("four")); 

Map<Integer, Optional<String>> map2 = map.entrySet().stream()
        .filter(e -> e.getKey() > 2)
        .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));

System.out.println(map2.toString());

测试

{3=Optional.empty, 4=Optional[four]}

要了解更多实用方法来帮助代码将值处理为可用不可用,而不是检查null值,我建议您参考documentation

【讨论】:

  • 是的,它可能会解决我的问题。但是,我的目标是用包括null 在内的新值恢复新的Map。这意味着我必须使用 .isPresent()? 来检查值?
  • @NikolasCharalambidist Optional 的想法是实现您想要的。您需要将第二个类型参数 String 替换为 Optional&lt;String&gt; 然后使用它。
  • Yahya,我最初对您的答案投了反对票,但我立即将其恢复,没有阅读您之前的评论。我投了反对票,因为您没有回答 OP 的要求,但后来我认为我太苛刻了,因为即使 OP 没有询问Optional,您也提供了一种解决方法。但是,解决此问题的更好方法是使用自定义收集器。无论如何,这是一个重复的问题,请检查链接的原始问题的答案以找出答案。很抱歉我的投票太快太苛刻了。
猜你喜欢
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多