【问题标题】:Instantiate a Map from a set of key objects, in Java在 Java 中从一组关键对象实例化 Map
【发布时间】:2021-06-05 04:59:21
【问题描述】:

给定一个我想用作键的对象Set,我怎样才能轻松获得一个Map 实例,将值保留为空?

目的是在确定要存储的值之前使用键预先填充映射。

当然,我可以创建一个空映射,然后循环这组可能的关键对象,同时对每个对象执行 put,并将 null 作为值。

Set< Month > months = EnumSet.of( Month.MARCH , Month.MAY , Month.JUNE ) ; 
Map< Month , String > map = new EnumMap<>( Month.class ) ;
for( Month month : months ) 
{
    map.put( month , null ) ;
}

我只是想知道是否有一个巧妙的技巧可以用更少的代码来做到这一点。类似于Map#keySet 的反义词。

【问题讨论】:

  • 什么样的Map?您可以编写自己的Map 实现,该实现接受Set 进行初始化和/或由Set 支持。否则是不可能的。使用 for 循环或 Stream(本质上与 for 循环相同)。 ... 编辑: 用键预填充Map 的原因是什么?
  • @BenjaminM 任何Map 实现都可以。我总是可以将该映射传递给我想要的另一个 Map 的构造函数。

标签: java dictionary set instantiation


【解决方案1】:
set.stream().collect(Collectors.toMap(k -> k, k -> null));

【讨论】:

  • 我似乎无法让该代码工作。我不确定运行时错误。我怀疑不容忍空值。见代码run live at IdeOne.com
  • 如果我们使用空字符串而不是 null 作为值,那么该代码确实有效。见this code on IdeOne.comMap&lt; Month , String &gt; map = Set.of( Month.MARCH , Month.MAY , Month.JUNE ).stream().collect( Collectors.toMap( k -&gt; k , k -&gt; "" ) );
【解决方案2】:

Collectors.toMap() 和像Map.of() 这样的静态工厂方法在内部使用Map.merge,如果键或值为空,则会抛出 NPE。

看到这个帖子:java-8-nullpointerexception-in-collectors-tomap。并在 OpenJDK 项目上查看此问题页面:JDK-8148463 Collectors.toMap fails on null values

您可以通过使用带有三个 args 签名的 Stream.collect 来解决问题。

collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)

类似:

Set< Month > months = EnumSet.of( Month.MARCH , Month.MAY , Month.JUNE ) ;         
Map< Month , String > myMap = 
        months.stream()
              .collect(
                  HashMap::new , 
                  ( map , val )-> map.put( val , null ) , 
                  HashMap::putAll
              );
              
System.out.println(myMap);

看到code run live at IdeOne.com

但我不确定这是否比您使用经典 for 循环的方法更具可读性或更优雅

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多