Reputation: 5
I have two HashMaps whose keys are String and whose values are MyObject. My goal is to merge these two hashmaps, and then return a hashmap containing all the objects from these to maps. But if the keys (Strings) are identical, instances with the same key should be stored as the same MyObject. I have successfully managed to do this.
My problem is that i´d like to update a field inside the instance with identical keys.
class MyObject
String name;
int counter;
MyObject(String name) {
this.name = name;
this.counter = 1;
}
// getters and setters...
My goal is to update the int counter every time the keys are identical in the hashmap.
This code will successfully merge these two maps, put i cant seem to find out how to update the field int counter in MyObject every time MyObject have the same keys.
class Main
HashMap<String, MyObject> map1 = new HashMap<>();
HashMap<String, MyObject> map2 = new HashMap<>();
//some code that will put some instances of MyObject into map1 and map2
// assume that least three instances have the same keys
HashMap<String, MyObject> map3 = new HashMap<>(map1);
map2.forEach((key, value) -> map3.merge(key, value, (v1, v2) -> new MyObject(v1.getName())));
Suppose these two objects have the same key;
MyObject.getCounter() = 3 in map1
MyObject.getCounter() = 5 in map2
The new MyObject.getCounter() should be 8.
Upvotes: 0
Views: 2417
Reputation: 40057
You can do it as follows:
Create some data
HashMap<String, MyObject> map1 = new HashMap<>();
HashMap<String, MyObject> map2 = new HashMap<>();
map1.put("A", new MyObject(2));
map1.put("B", new MyObject(4));
map1.put("C", new MyObject(10));
map2.put("C", new MyObject(10));
map2.put("B", new MyObject(8));
Now create the map
Map<String, MyObject> result = Stream
.concat(map1.entrySet().stream(),
map2.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey,
Entry::getValue, (a, b) -> {
a.setCounter(a.getCounter() + b.getCounter());
return a;
}, HashMap::new));
result.entrySet().forEach(System.out::println);
Prints
A=2
B=12
C=20
You could also use the following, prior to collection.
Map<String, MyObject> result = Stream.of(map1,map2)
.flatMap(map->map.entrySet().stream())
.collect(...);
Class definition
class MyObject {
int value;
public MyObject(int v) {
this.value = v;
}
public int getCounter() {
return value;
}
public void setCounter(int a) {
value = a;
}
public String toString() {
return value + "";
}
}
Upvotes: 3
Reputation: 17920
You have to set the counter
value of the new MyObject
that you create.
If the class MyObject
has a setter,
Map<String, MyObject> map3 = new HashMap<>(map1);
map2.forEach((key, value) -> map3.merge(key, value, (v1, v2) -> {
MyObject myObject = new MyObject(v1.getName());
myObject.setCounter(v1.getCounter() + v2.getCounter());
return myObject;
}));
If you have an overloaded constructor accepting the name and the counter like,
MyObject(String name, int counter) {
this.name = name;
this.counter = counter;
}
then, you can do like,
map2.forEach((key, value) -> map3.merge(key, value,
(v1, v2) -> new MyObject(v1.getName(), v1.getCounter() + v2.getCounter())));
Upvotes: 1