В Java 8 как преобразовать карту <K, V> в другую карту <K, V> с помощью лямбда?
Я только начал смотреть на Java 8 и попробовать lambdas. Я думал, что попытаюсь переписать очень простую вещь, которую я написал недавно. Мне нужно превратить карту строк в столбцы в другую карту строки в столбец, где столбец на новой карте является защитной копией столбца на первой карте. Столбец имеет конструктор копирования. Самое близкое, что я до сих пор знаю:
Map<String, Column> newColumnMap= new HashMap<>();
originalColumnMap.entrySet().stream().forEach(x -> newColumnMap.put(x.getKey(), new Column(x.getValue())));
но я уверен, что должен быть более хороший способ сделать это, и я был бы признателен за некоторые советы.
Ответы
Ответ 1
Вы можете использовать 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) {}
}
}
Ответ 2
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);
}
});
Что мы можем упростить в лямбда:
map.forEach((s, integer) -> map2.put(s, integer));
И поскольку мы просто вызываем существующий метод, мы можем использовать ссылку на метод, которая дает нам:
map.forEach(map2::put);
Ответ 3
Способ без повторной вставки всех записей в новую карту должен быть самым быстрым, потому что HashMap.clone
внутренне выполняет переименование.
Map<String, Column> newColumnMap = originalColumnMap.clone();
newColumnMap.replaceAll((s, c) -> new Column(c));
Ответ 4
Держите его простым и используйте 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())
);
Ответ 5
Вот еще один способ, который дает вам доступ к ключу и значению в одно и то же время, если вам нужно сделать какое-то преобразование.
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));
Ответ 6
Если вы не возражаете против использования сторонних библиотек, cyclops-react lib имеет расширения для всех JDK Collection, включая Map. Вы можете напрямую использовать методы map или bimap для преобразования вашей карты. MapX можно построить из существующей Карты, например.
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 extends Map, сгенерированная карта также может быть определена как
Map<String, Column> y
Ответ 7
Если вы используете Guava (минимум v11) в своем проекте, вы можете использовать Maps :: transformValues.
Map<String, Column> newColumnMap = Maps.transformValues(
originalColumnMap,
Column::new // equivalent to: x -> new Column(x)
)