Ответ 1
Если вы используете Java 8, вы можете использовать новый метод merge.
m2.forEach((k, v) -> m.merge(k, v, (v1, v2) -> v1 + v2));
ı пытаюсь объединить несколько хэш-карт, также суммировать значения одного и того же ключа, ı хочу объяснить мою проблему с примером игрушки следующим образом
HashMap<String, Integer> m = new HashMap<>();
HashMap<String, Integer> m2 = new HashMap<>();
m.put("apple", 2);
m.put("pear", 3);
m2.put("apple", 9);
m2.put("banana", 6);
ı поставил putall
m.putAll(м2);
вывод выглядит следующим образом {banana = 6, apple = 9, pear = 3}
но его результат неверен для этой проблемы. ı хотите выводить как
{banana = 6, apple = 11, pear = 3}
как можно получить этот результат в java?
Если вы используете Java 8, вы можете использовать новый метод merge.
m2.forEach((k, v) -> m.merge(k, v, (v1, v2) -> v1 + v2));
Это очень хороший вариант использования для потоков Java 8. Вы можете объединить потоки записей, а затем собрать их на новой карте:
Map<String, Integer> combinedMap = Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.summingInt(Map.Entry::getValue)));
В этом решении есть много приятных вещей, в том числе возможность сделать его параллельным, расширяться до максимально возможного количества карт и иметь возможность тривиально фильтровать карты, если это необходимо. Он также не требует, чтобы оригинальные карты изменялись.
Этот метод должен сделать это (в Java 5 +)
public static <K> Map<K, Integer> mergeAndAdd(Map<K, Integer>... maps) {
Map<K, Integer> result = new HashMap<>();
for (Map<K, Integer> map : maps) {
for (Map.Entry<K, Integer> entry : map.entrySet()) {
K key = entry.getKey();
Integer current = result.get(key);
result.put(key, current == null ? entry.getValue() : entry.getValue() + current);
}
}
return result;
}
Здесь моя быстрая и грязная реализация:
import java.util.HashMap;
import java.util.Map;
public class MapMerger {
public static void main(String[] args) {
HashMap<String, Integer> m = new HashMap<>();
HashMap<String, Integer> m2 = new HashMap<>();
m.put("apple", 2);
m.put("pear", 3);
m2.put("apple", 9);
m2.put("banana", 6);
final Map<String, Integer> result = (new MapMerger()).mergeSumOfMaps(m, m2);
System.out.println(result);
}
public Map<String, Integer> mergeSumOfMaps(Map<String, Integer>... maps) {
final Map<String, Integer> resultMap = new HashMap<>();
for (final Map<String, Integer> map : maps) {
for (final String key : map.keySet()) {
final int value;
if (resultMap.containsKey(key)) {
final int existingValue = resultMap.get(key);
value = map.get(key) + existingValue;
}
else {
value = map.get(key);
}
resultMap.put(key, value);
}
}
return resultMap;
}
}
Вывод:
{banana=6, apple=11, pear=3}
Есть некоторые вещи, которые вы должны сделать (например, проверка нуля), и я не уверен, что это самый быстрый. Кроме того, это относится к целым числам. Я попытался сделать один с использованием дженериков класса Number
, но вам понадобится этот метод для каждого типа (byte, int, short, longer и т.д.)
ı улучшить код Lucas Ross. вместо того, чтобы вводить карту по одной в функции ı, дают все карты один раз для работы с arraylist hashmap, подобным этому
public HashMap<String, Integer> mergeAndAdd(ArrayList<HashMap<String, Integer>> maplist) {
HashMap<String, Integer> result = new HashMap<>();
for (HashMap<String, Integer> map : maplist) {
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer current = result.get(key);
result.put(key, current == null ? entry.getValue() : entry.getValue() + current);
}
}
return result;
}
}
он тоже работает. благодаря вечному
Что-то вроде этого должно работать:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String map1_key = entry.getKey();
int map1_value = entry.getValue();
//check:
if(map2.get(map1_key)!=null){
int map2_value = map2.get(map1_key);
//merge:
map3.put(map1_key,map1_value+map2_value);
}else{
map3.put(map1_key,map1_value);
}
}
for (Map.Entry<String, Integer> entry2 : map2.entrySet()) {
String map2_key = entry2.getKey();
int map2_value = entry2.getValue();
//check:
if(map1.get(map2_key)!=null){
int map1_value = map1.get(map2_key);
//merge:
map3.put(map2_key,map1_value+map2_value);
}else{
map3.put(map2_key,map2_value);
}
}
Если ключ существует, добавьте к нему значение. Если не вставить.
Вот простой пример, который объединяет одну карту в другую:
Foo oldVal = map.get(key);
if oldVal == null
{
map2.put(key, newVal);
}
else
{
map2.put(key, newVal + oldVal);
}
Очевидно, вам нужно перебрать первую карту, чтобы вы могли обрабатывать все ее записи, но это тривиально.
Предположим, у вас есть много HashMaps: HashMap<String,Integer> map1, map2, map3;
Тогда вы можете использовать потоки Java 8:
List<Map<String,Integer>> mapList = Arrays.asList(map1, map2, map3);
Map<String,Integer> combinedMap = mapList.stream()
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.groupingBy(Entry::getKey,
Collectors.summingInt(Entry::getValue)));