如何使用lambda初始化地图?

Mik*_*kis 9 java collections lambda dictionary java-8

我想在单个语句中声明一个完全填充的映射字段(可能包含几个嵌套语句),如下所示:

private static final Map<Integer,Boolean> map = 
    something-returning-an-unmodifiable-fully-populated-HashMap;
Run Code Online (Sandbox Code Playgroud)

匿名初始化程序不会这样做,因为调用返回新填充映射的函数不会这样做:它们需要两个顶级语句:一个用于变量声明,一个用于方法或初始化程序.

双花括号({{}})成语将起作用,但它会创建一个扩展的全新类HashMap<>,我不喜欢这个代表的开销.

Java 8的lambdas是否可能提供更好的方法来实现这一目标?

Tun*_*aki 9

如果要Map在单个语句中初始化a ,则可以使用Collectors.toMap.

想象一下,你想构建一个Map<Integer, Boolean>整数映射到调用某个函数的结果f:

private static final Map<Integer,Boolean> MAP = 
        Collections.unmodifiableMap(IntStream.range(0, 1000)
                                             .boxed()
                                             .collect(Collectors.toMap(i -> i, i -> f(i))));

private static final boolean f(int i) {
    return Math.random() * 100 > i;
}
Run Code Online (Sandbox Code Playgroud)

如果您想使用"静态"已知值对其进行初始化,例如答案中的示例,则可以滥用Stream API,如下所示:

private static final Map<Integer, Boolean> MAP = 
       Stream.of(new Object[] { 1, false }, new Object[] { 2, true })
             .collect(Collectors.toMap(s -> (int) s[0], s -> (boolean) s[1]));
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个真正的滥用,我个人永远不会使用它:如果你想构建一个具有已知静态值的Map,使用Streams没有任何好处,你最好使用静态初始化器.

  • 是的,既然我们有了解决方案,我们可能会寻找一个可以解决的问题...... (4认同)

Mik*_*kis 4

以下是如何在 Java 8 中使用 lambda 在单个语句中实现字段初始值设定项。

private static final Map<Integer,Boolean> map =
        ((Supplier<Map<Integer,Boolean>>)() -> {
            Map<Integer,Boolean> mutableMap = new HashMap<>();
            mutableMap.put( 1, false );
            mutableMap.put( 2, true );
            return Collections.unmodifiableMap( mutableMap );
        }).get();
Run Code Online (Sandbox Code Playgroud)

Java 9解决方案:

private static final Map<Integer,Boolean> map = Map.of( 1, false, 2, true );
Run Code Online (Sandbox Code Playgroud)

如果您有超过 10 个条目,Map.of()则不起作用,因此您需要:

private static final Map<Integer,Boolean> map = Map.ofEntries( 
        Map.entry( 1, false ), 
        Map.entry( 2, true ), 
        Map.entry( 3, false ), 
        Map.entry( 4, true ), 
        Map.entry( 5, false ), 
        Map.entry( 6, true ), 
        Map.entry( 7, false ), 
        Map.entry( 8, true ), 
        Map.entry( 9, false ), 
        Map.entry( 10, true ), 
        Map.entry( 11, false ) );
Run Code Online (Sandbox Code Playgroud)