在 Java 8 中,如何使用 lambda 将 Map<K,V> 转换为另一个 Map<K,V>?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22742974/
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
In Java 8 how do I transform a Map<K,V> to another Map<K,V> using a lambda?
提问by annesadleir
I've just started looking at Java 8 and to try out lambdas I thought I'd try to rewrite a very simple thing I wrote recently. I need to turn a Map of String to Column into another Map of String to Column where the Column in the new Map is a defensive copy of the Column in the first Map. Column has a copy constructor. The closest I've got so far is:
我刚刚开始研究 Java 8 并尝试使用 lambdas 我想我会尝试重写我最近写的一个非常简单的东西。我需要将字符串到列的映射转换为另一个字符串到列的映射,其中新映射中的列是第一个映射中列的防御副本。列有一个复制构造函数。到目前为止我最接近的是:
Map<String, Column> newColumnMap= new HashMap<>();
originalColumnMap.entrySet().stream().forEach(x -> newColumnMap.put(x.getKey(), new Column(x.getValue())));
but I'm sure there must be a nicer way to do it and I'd be grateful for some advice.
但我相信一定有更好的方法来做到这一点,我会很感激一些建议。
采纳答案by McDowell
You could use a Collector:
您可以使用收集器:
import java.util.*;
import java.util.stream.Collectors;
public class Defensive {
public static void main(String[] args) {
Map<String, Column> original = new HashMap<>();
original.put("foo", new Column());
original.put("bar", new Column());
Map<String, Column> copy = original.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> new Column(e.getValue())));
System.out.println(original);
System.out.println(copy);
}
static class Column {
public Column() {}
public Column(Column c) {}
}
}
回答by Arrem
Map<String, Integer> map = new HashMap<>();
map.put("test1", 1);
map.put("test2", 2);
Map<String, Integer> map2 = new HashMap<>();
map.forEach(map2::put);
System.out.println("map: " + map);
System.out.println("map2: " + map2);
// Output:
// map: {test2=2, test1=1}
// map2: {test2=2, test1=1}
You can use the forEach
method to do what you want.
您可以使用该forEach
方法来做您想做的事。
What you're doing there is:
你在那里做的是:
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
map2.put(s, integer);
}
});
Which we can simplify into a lambda:
我们可以简化为一个 lambda:
map.forEach((s, integer) -> map2.put(s, integer));
And because we're just calling an existing method we can use a method reference, which gives us:
因为我们只是调用一个现有的方法,所以我们可以使用方法引用,它给了我们:
map.forEach(map2::put);
回答by leventov
The way without re-inserting all entries into the new map should be the fastestit won't because HashMap.clone
internally performs rehash as well.
不将所有条目重新插入新地图的方式应该是最快的,因为HashMap.clone
内部也执行重新哈希。
Map<String, Column> newColumnMap = originalColumnMap.clone();
newColumnMap.replaceAll((s, c) -> new Column(c));
回答by John McClean
If you don't mind using 3rd party libraries, my cyclops-reactlib has extensions for all JDK Collectiontypes, including Map. You can directly use the map or bimap methods to transform your Map. A MapX can be constructed from an existing Map eg.
如果您不介意使用 3rd 方库,我的cyclops-react库具有适用于所有JDK 集合类型的扩展,包括Map。您可以直接使用 map 或 bimap 方法来转换您的地图。MapX 可以从现有的 Map 构建,例如。
MapX<String, Column> y = MapX.fromMap(orgColumnMap)
.map(c->new Column(c.getValue());
If you also wish to change the key you can write
如果您还想更改密钥,您可以编写
MapX<String, Column> y = MapX.fromMap(orgColumnMap)
.bimap(this::newKey,c->new Column(c.getValue());
bimap can be used to transform the keys and values at the same time.
bimap 可用于同时转换键和值。
As MapX extends Map the generated map can also be defined as
随着 MapX 扩展 Map,生成的地图也可以定义为
Map<String, Column> y
回答by Lucas Ross
Here is another way that gives you access to the key and the value at the same time, in case you have to do some kind of transformation.
这是另一种让您同时访问键和值的方法,以防您必须进行某种转换。
Map<String, Integer> pointsByName = new HashMap<>();
Map<String, Integer> maxPointsByName = new HashMap<>();
Map<String, Double> gradesByName = pointsByName.entrySet().stream()
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(
entry.getKey(), ((double) entry.getValue() /
maxPointsByName.get(entry.getKey())) * 100d))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
回答by Anant Khurana
Keep it Simple and use Java 8:-
保持简单并使用 Java 8:-
Map<String, AccountGroupMappingModel> mapAccountGroup=CustomerDAO.getAccountGroupMapping();
Map<String, AccountGroupMappingModel> mapH2ToBydAccountGroups =
mapAccountGroup.entrySet().stream()
.collect(Collectors.toMap(e->e.getValue().getH2AccountGroup(),
e ->e.getValue())
);
回答by Andrea Bergonzo
If you use Guava (v11 minimum) in your project you can use Maps::transformValues.
如果您在项目中使用 Guava(最低 v11),您可以使用Maps::transformValues。
Map<String, Column> newColumnMap = Maps.transformValues(
originalColumnMap,
Column::new // equivalent to: x -> new Column(x)
)
Note: The values of this map are evaluated lazily. If the transformation is expensive you can copy the result to a new map like suggested in the Guava docs.
注意:此地图的值是惰性计算的。如果转换很昂贵,您可以像 Guava 文档中建议的那样将结果复制到新地图。
To avoid lazy evaluation when the returned map doesn't need to be a view, copy the returned map into a new map of your choosing.