在Java 8中,如何使用lambda将Map <K,V>转换为另一个Map <K,V>?
我刚刚开始研究Java 8并尝试使用lambdaexpression式,我想我会尝试重写最近编写的一个非常简单的东西。 我需要将一个string映射到列到另一个string映射到列新地图列是在第一个地图列的防御副本。 列有一个拷贝构造函数。 我到目前为止最接近的是:
Map<String, Column> newColumnMap= new HashMap<>(); originalColumnMap.entrySet().stream().forEach(x -> newColumnMap.put(x.getKey(), new Column(x.getValue())));
但我确定有一个更好的方法来做到这一点,我会很感激的一些build议。
你可以使用一个收集器 :
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) {} } }
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}
你可以使用forEach
方法来做你想做的事情。
你在做什么是:
map.forEach(new BiConsumer<String, Integer>() { @Override public void accept(String s, Integer integer) { map2.put(s, integer); } });
我们可以简化为一个lambda:
map.forEach((s, integer) -> map2.put(s, integer));
因为我们只是调用一个现有的方法,所以我们可以使用一个方法引用 ,它给了我们:
map.forEach(map2::put);
不重新插入所有条目到新映射的方式应该是最快的 ,因为HashMap.clone
也在内部执行rehash。
Map<String, Column> newColumnMap = originalColumnMap.clone(); newColumnMap.replaceAll((s, c) -> new Column(c));
如果您不介意使用第三方库,我的独眼巨人反应 lib具有扩展所有JDK集合types,包括地图 。 您可以直接使用地图或bimap方法来转换您的地图。 MapX可以从现有的Map构build,
MapX<String, Column> y = MapX.fromMap(orgColumnMap) .map(c->new Column(c.getValue());
如果你也想改变你可以写的密钥
MapX<String, Column> y = MapX.fromMap(orgColumnMap) .bimap(this::newKey,c->new Column(c.getValue());
bimap可以用来同时转换键和值。
由于MapX扩展了Map,生成的地图也可以定义为
Map<String, Column> y
这是另一种方式,可以让您在同一时间访问密钥和价值,以防万一需要进行某种转换。
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));