如何将单个键值添加到现有 Java 8 流?
How to add a single Key value to existing Java 8 stream?
这是我填充静态地图的方法
public static final Map<String, FooBar> mapEnum =
Arrays.stream(FooBarEnum.values())
.collect(Collectors.toMap(e-> StringUtils.upperCase(e.name), e -> e));
我想向该地图添加另一个键值。
mapEnum.put("xx", FooBar.A);
这是枚举
public enum FooBar {
A("a"), B("b"), C("c");
}
构建完地图后我的静态地图将如下所示
{"a":FooBar.A, "b": FooBar.B, "c": FooBar.C, "xx": Foobar.A}
是否可以将显式 put 调用包含到 Collectors.toMap()
中?
实际上我认为没有必要为此使用 Java Streams。您可以简单地使用 static
块来初始化 mapEnum
和 put
其中的其他值:
public static final Map<String, FooBar> mapEnum;
static {
mapEnum = Arrays.stream(FooBar.values())
.collect(Collectors.toMap(FooBar::getName, Function.identity()));
mapEnum.put("xx", FooBar.A);
// ...
}
Collectors.toMap()
: There are no guarantees on the type, mutability, serializability, or thread-safety of the {@code Map} returned.
为了确保Collectors.toMap()
返回的Map
的可变性,所以你以后可以使用Map.put()
更好地使用这个:
Arrays.stream(FooBar.values())
.collect(Collectors.toMap(Function.identity(), Function.identity(), (a, b) -> a, HashMap::new));
如果你真的想使用 java 流,你可以使用这个:
public static final Map<String, FooBar> mapEnum = Stream.concat(
Stream.of(FooBar.values()).map(e -> Map.entry(e.getName(), e)),
Stream.of(Map.entry("xx", FooBar.A))
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
或者如果您还想将所有名称添加到枚举值本身,您可以像这样更改 class:
public static enum FooBar {
A("a", "xx"), B("b"), C("c");
private String[] names;
FooBar(String... names) {
this.names = names;
}
public String[] getNames() {
return names;
}
}
并使用它来创建地图:
public static final Map<String, FooBar> mapEnum = Stream.of(FooBar.values())
.flatMap(e -> Arrays.stream(e.getNames()).map(n -> Map.entry(n, e)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
在 Java 9 之前使用 new AbstractMap.SimpleEntry<>()
而不是 Map.entry()
。如果您需要对地图进行排序,请使用 LinkedHashMap::new
和 Collectors.toMap()
。
您可以使用Collectors::collectAndThen
修改生成的地图
Arrays.stream(FooBarEnum.values())
.collect(Collectors.collectAndThen(
Collectors.toMap(e-> StringUtils.upperCase(e.name),
Function.identity()), FooBarEnum::addCustom));
以下方法在枚举中
static Map<String, FooBar> addCustom(Map<String, FooBarEnum> map) {
map.put("xx", FooBar.A);
return map;
}
您不能直接将其传递给 Collectors.toMap()。您可以在 javadocs 中看到所有可用的覆盖:https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function- .
但是,在使用 Stream.concat 调用 toMap 之前,您可以确保流具有构建地图所需的所有对。您连接枚举中的对,以及要添加的手动对。
我的独立代码必须定义 Pair class,但由于您使用了 StringUtils,我想您有一个已经包含 Pair 的库,因此您不需要定义它。
代码:
import java.util.*;
import java.util.stream.*;
public class Main {
private static enum FooBar {
A("a"), B("b"), C("c");
private String name;
FooBar(String name) {
this.name = name;
}
}
public static class Pair {
String a;
FooBar b;
Pair(String a, FooBar b) {
this.a = a;
this.b = b;
}
}
public static void main(String [] args) {
System.out.println(
Stream.concat(
Arrays.stream(FooBar.values()).map(e -> new Pair(e.name.toUpperCase(), e)),
Stream.of(new Pair("xx", FooBar.A))
)
.collect(Collectors.toMap(pair -> pair.a, pair -> pair.b))
);
}
}
输出:
{xx=A, A=A, B=B, C=C}
如果您愿意使用第三方库,您可以使用 Eclipse Collections.
创建静态 ImmutableMap
与 Stream
内联
public static final ImmutableMap<String, FooBar> MAP_ENUM =
Arrays.stream(FooBar.values())
.collect(Collectors2.toMap(FooBar::getName, fooBar -> fooBar))
.withKeyValue("xx", FooBar.A)
.toImmutable();
public enum FooBar {
A("a"), B("b"), C("c");
private String name;
FooBar(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
您还可以使用本机 Eclipse Collections API 稍微简化代码。
public static final ImmutableMap<String, FooBar> MAP_ENUM =
ArrayAdapter.adapt(FooBar.values())
.groupByUniqueKey(FooBar::getName)
.withKeyValue("xx", FooBar.A)
.toImmutable();
注意:我是 Eclipse Collections 的提交者
这是我填充静态地图的方法
public static final Map<String, FooBar> mapEnum =
Arrays.stream(FooBarEnum.values())
.collect(Collectors.toMap(e-> StringUtils.upperCase(e.name), e -> e));
我想向该地图添加另一个键值。
mapEnum.put("xx", FooBar.A);
这是枚举
public enum FooBar {
A("a"), B("b"), C("c");
}
构建完地图后我的静态地图将如下所示
{"a":FooBar.A, "b": FooBar.B, "c": FooBar.C, "xx": Foobar.A}
是否可以将显式 put 调用包含到 Collectors.toMap()
中?
实际上我认为没有必要为此使用 Java Streams。您可以简单地使用 static
块来初始化 mapEnum
和 put
其中的其他值:
public static final Map<String, FooBar> mapEnum;
static {
mapEnum = Arrays.stream(FooBar.values())
.collect(Collectors.toMap(FooBar::getName, Function.identity()));
mapEnum.put("xx", FooBar.A);
// ...
}
Collectors.toMap()
: There are no guarantees on the type, mutability, serializability, or thread-safety of the {@code Map} returned.
为了确保Collectors.toMap()
返回的Map
的可变性,所以你以后可以使用Map.put()
更好地使用这个:
Arrays.stream(FooBar.values())
.collect(Collectors.toMap(Function.identity(), Function.identity(), (a, b) -> a, HashMap::new));
如果你真的想使用 java 流,你可以使用这个:
public static final Map<String, FooBar> mapEnum = Stream.concat(
Stream.of(FooBar.values()).map(e -> Map.entry(e.getName(), e)),
Stream.of(Map.entry("xx", FooBar.A))
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
或者如果您还想将所有名称添加到枚举值本身,您可以像这样更改 class:
public static enum FooBar {
A("a", "xx"), B("b"), C("c");
private String[] names;
FooBar(String... names) {
this.names = names;
}
public String[] getNames() {
return names;
}
}
并使用它来创建地图:
public static final Map<String, FooBar> mapEnum = Stream.of(FooBar.values())
.flatMap(e -> Arrays.stream(e.getNames()).map(n -> Map.entry(n, e)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
在 Java 9 之前使用 new AbstractMap.SimpleEntry<>()
而不是 Map.entry()
。如果您需要对地图进行排序,请使用 LinkedHashMap::new
和 Collectors.toMap()
。
您可以使用Collectors::collectAndThen
修改生成的地图
Arrays.stream(FooBarEnum.values())
.collect(Collectors.collectAndThen(
Collectors.toMap(e-> StringUtils.upperCase(e.name),
Function.identity()), FooBarEnum::addCustom));
以下方法在枚举中
static Map<String, FooBar> addCustom(Map<String, FooBarEnum> map) {
map.put("xx", FooBar.A);
return map;
}
您不能直接将其传递给 Collectors.toMap()。您可以在 javadocs 中看到所有可用的覆盖:https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function- .
但是,在使用 Stream.concat 调用 toMap 之前,您可以确保流具有构建地图所需的所有对。您连接枚举中的对,以及要添加的手动对。
我的独立代码必须定义 Pair class,但由于您使用了 StringUtils,我想您有一个已经包含 Pair 的库,因此您不需要定义它。
代码:
import java.util.*;
import java.util.stream.*;
public class Main {
private static enum FooBar {
A("a"), B("b"), C("c");
private String name;
FooBar(String name) {
this.name = name;
}
}
public static class Pair {
String a;
FooBar b;
Pair(String a, FooBar b) {
this.a = a;
this.b = b;
}
}
public static void main(String [] args) {
System.out.println(
Stream.concat(
Arrays.stream(FooBar.values()).map(e -> new Pair(e.name.toUpperCase(), e)),
Stream.of(new Pair("xx", FooBar.A))
)
.collect(Collectors.toMap(pair -> pair.a, pair -> pair.b))
);
}
}
输出:
{xx=A, A=A, B=B, C=C}
如果您愿意使用第三方库,您可以使用 Eclipse Collections.
创建静态ImmutableMap
与 Stream
内联
public static final ImmutableMap<String, FooBar> MAP_ENUM =
Arrays.stream(FooBar.values())
.collect(Collectors2.toMap(FooBar::getName, fooBar -> fooBar))
.withKeyValue("xx", FooBar.A)
.toImmutable();
public enum FooBar {
A("a"), B("b"), C("c");
private String name;
FooBar(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
您还可以使用本机 Eclipse Collections API 稍微简化代码。
public static final ImmutableMap<String, FooBar> MAP_ENUM =
ArrayAdapter.adapt(FooBar.values())
.groupByUniqueKey(FooBar::getName)
.withKeyValue("xx", FooBar.A)
.toImmutable();
注意:我是 Eclipse Collections 的提交者