java 如何使用 lambda 初始化地图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32868665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to initialize a map using a lambda?
提问by Mike Nakis
I want to declare a fully populated map field in a single statement, (which may contain several nested statements,) like this:
我想在单个语句(可能包含多个嵌套语句)中声明一个完全填充的地图字段,如下所示:
private static final Map<Integer,Boolean> map =
something-returning-an-unmodifiable-fully-populated-HashMap;
Anonymous initializers won't do, for the same reason that invoking a function which returns a new populated map won't do: they require two top-level statements: one for the variable declaration, and one for the method or initializer.
匿名初始化程序不会这样做,原因与调用返回新填充映射的函数不会这样做的原因相同:它们需要两个顶级语句:一个用于变量声明,另一个用于方法或初始化程序。
The double curly bracket ({{
and }}
) idiom will work, but it creates a whole new class which extends HashMap<>
, and I do not like the overhead represented by this.
双花括号 ( {{
and }}
) 习语会起作用,但它创建了一个全新的类扩展HashMap<>
,我不喜欢由此表示的开销。
Do the lambdas of Java 8 perhaps offer a better way of accomplishing this?
Java 8 的 lambda 表达式是否提供了更好的方法来实现这一点?
采纳答案by Mike Nakis
Here is how to implement a field initializer in Java 8 in a single statement using a lambda.
以下是如何使用 lambda 在单个语句中在 Java 8 中实现字段初始值设定项。
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();
Java 9 solution:
Java 9 解决方案:
private static final Map<Integer,Boolean> map = Map.of( 1, false, 2, true );
and if you have more than 10 entries, Map.of()
won't work, so you need this:
如果您有 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 ) );
回答by Tunaki
If you want to initialize a Map
in a single statement, you can use Collectors.toMap
.
如果要Map
在单个语句中初始化 a ,可以使用Collectors.toMap
.
Imagine you want to build a Map<Integer, Boolean>
mapping an integer to the result of calling some function f
:
想象一下,您想要构建一个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;
}
If you want to initialize it with "static" known values, like the example in your answer, you can abuse the Stream API like this:
如果您想使用“静态”已知值对其进行初始化,例如您的答案中的示例,您可以像这样滥用 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]));
Note that this is a real abuseand I personally would never use it: if you want to construct a Map with known static values, there is nothing to gain from using Streams and you would be better off to use a static initializer.
请注意,这是一种真正的滥用,我个人永远不会使用它:如果您想构造一个具有已知静态值的 Map,则使用 Streams 没有任何好处,最好使用静态初始化程序。
回答by Tagir Valeev
If you really want to do initialize the map in single statement, you can write your custom builder and use it in your project. Something like this:
如果您真的想在单个语句中初始化地图,您可以编写自定义构建器并在您的项目中使用它。像这样的东西:
public class MapBuilder<K, V> {
private final Map<K, V> map;
private MapBuilder(Map<K, V> map) {
this.map = map;
}
public MapBuilder<K, V> put(K key, V value) {
if(map == null)
throw new IllegalStateException();
map.put(key, value);
return this;
}
public MapBuilder<K, V> put(Map<? extends K, ? extends V> other) {
if(map == null)
throw new IllegalStateException();
map.putAll(other);
return this;
}
public Map<K, V> build() {
Map<K, V> m = map;
map = null;
return Collections.unmodifiableMap(m);
}
public static <K, V> MapBuilder<K, V> unordered() {
return new MapBuilder<>(new HashMap<>());
}
public static <K, V> MapBuilder<K, V> ordered() {
return new MapBuilder<>(new LinkedHashMap<>());
}
public static <K extends Comparable<K>, V> MapBuilder<K, V> sorted() {
return new MapBuilder<>(new TreeMap<>());
}
public static <K, V> MapBuilder<K, V> sorted(Comparator<K> comparator) {
return new MapBuilder<>(new TreeMap<>(comparator));
}
}
Usage example:
用法示例:
Map<Integer, Boolean> map = MapBuilder.<Integer, Boolean>unordered()
.put(1, true).put(2, false).build();
This works in Java-7 as well.
这也适用于 Java-7。
As a side note, we will likely to see something like Map.of(1, true, 2, false)
in Java-9. See JDK-8048330for details.
作为旁注,我们可能会Map.of(1, true, 2, false)
在 Java-9 中看到类似的东西。有关详细信息,请参阅JDK-8048330。
回答by muued
Google Guava's Maps classprovides some nice utility methods for this. Additionally, there is the ImmutableMap classand its static methods. Have a look at:
Google Guava 的 Maps 类为此提供了一些不错的实用方法。此外,还有ImmutableMap 类及其静态方法。看一下:
ImmutableMap.of(key1, value1, key2, value2, ...);
Maps.uniqueIndex(values, keyExtractor);
Maps.toMap(keys, valueMapper);