条目集上的 Java 8 流映射
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27228961/
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
Java 8 stream map on entry set
提问by Wil Selwood
I'm trying to perform a map operation on each entry in a Map
object.
我正在尝试对Map
对象中的每个条目执行映射操作。
I need to take a prefix off the key and convert the value from one type to another. My code is taking configuration entries from a Map<String, String>
and converting to a Map<String, AttributeType>
(AttributeType
is just a class holding some information. Further explanation is not relevant for this question.)
我需要去掉键的前缀并将值从一种类型转换为另一种类型。我的代码正在从 a 获取配置条目Map<String, String>
并转换为Map<String, AttributeType>
(AttributeType
只是一个包含一些信息的类。进一步的解释与这个问题无关。)
The best I have been able to come up with using the Java 8 Streams is the following:
我能想出的最好的使用 Java 8 Streams 如下:
private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
int subLength = prefix.length();
return input.entrySet().stream().flatMap((Map.Entry<String, Object> e) -> {
HashMap<String, AttributeType> r = new HashMap<>();
r.put(e.getKey().substring(subLength), AttributeType.GetByName(e.getValue()));
return r.entrySet().stream();
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
Being unable to construct an Map.Entry
due to it being an interface causes the creation of the single entry Map
instance and the use of flatMap()
, which seems ugly.
Map.Entry
由于它是接口而无法构造 an会导致创建单条目Map
实例并使用flatMap()
,这看起来很丑陋。
Is there a better alternative? It seems nicer to do this using a for loop:
有更好的选择吗?使用 for 循环执行此操作似乎更好:
private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
Map<String, AttributeType> result = new HashMap<>();
int subLength = prefix.length();
for(Map.Entry<String, String> entry : input.entrySet()) {
result.put(entry.getKey().substring(subLength), AttributeType.GetByName( entry.getValue()));
}
return result;
}
Should I avoid the Stream API for this? Or is there a nicer way I have missed?
我应该为此避免 Stream API 吗?或者有没有更好的方法我错过了?
采纳答案by Smutje
Simply translating the "old for loop way" into streams:
简单地将“旧的 for 循环方式”翻译成流:
private Map<String, String> mapConfig(Map<String, Integer> input, String prefix) {
int subLength = prefix.length();
return input.entrySet().stream()
.collect(Collectors.toMap(
entry -> entry.getKey().substring(subLength),
entry -> AttributeType.GetByName(entry.getValue())));
}
回答by Dawid Pancerz
Question might be a little dated, but you could simply use AbstractMap.SimpleEntry<> as follows:
问题可能有点过时,但您可以简单地使用 AbstractMap.SimpleEntry<> 如下:
private Map<String, AttributeType> mapConfig(
Map<String, String> input, String prefix) {
int subLength = prefix.length();
return input.entrySet()
.stream()
.map(e -> new AbstractMap.SimpleEntry<>(
e.getKey().substring(subLength),
AttributeType.GetByName(e.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
any other Pair-like value object would work too (ie. ApacheCommons Pair tuple).
任何其他类似 Pair 的值对象也可以工作(即 ApacheCommons Pair 元组)。
回答by user_3380739
Here is a shorter solution by AbacusUtil
这是AbacusUtil 的一个较短的解决方案
Stream.of(input).toMap(e -> e.getKey().substring(subLength),
e -> AttributeType.GetByName(e.getValue()));
回答by Lóránt Miglécz
Please make the following part of the Collectors API:
请制作收藏家 API 的以下部分:
<K, V> Collector<? super Map.Entry<K, V>, ?, Map<K, V>> toMap() {
return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);
}
回答by M. Justin
On Java 9 or later, Map.entry
can be used, so long as you know that neither the key nor value will be null. If either value could legitimately be null, AbstractMap.SimpleEntry
(as suggested in another answer) or AbstractMap.SimpleImmutableEntry
would be the way to go.
在 Java 9 或更高版本上,Map.entry
可以使用,只要您知道键和值都不为空。如果任何一个值都可以合法地为空,AbstractMap.SimpleEntry
(如另一个答案中所建议的那样)或者AbstractMap.SimpleImmutableEntry
是可行的方法。
private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
int subLength = prefix.length();
return input.entrySet().stream().map(e ->
Map.entry(e.getKey().substring(subLength), AttributeType.GetByName(e.getValue())));
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}