I am working on a program where I need to take a list of objects and put them in a HashMap
, using the class name as the key and the instance as the value.
I have the following code:
pets2.stream().forEach(pt -> animals.put(pt.getClass().getSimpleName(), pt));
Where pets2
is my list of animals is my HashMap
. However, when I run this and then print the HashMap
, only two objects from the list have been added into the Map
.
Not even the first two, just two of them. Any idea as to what the issue is and how I can fix it?
CodePudding user response:
If you have multiple instances of the same in a list you need, you will lose information if only a single object will represent a value.
Instead, you have to group the object mapped to the same key (belonging to the same class) into a collection.
With stream API, you can do it by using the built-in collector Collectors.groupingBy()
, which expects a classifier function that determines how to extract the key from an element of the stream. By default, values mapped to the same key will be grouped into a list.
Example (substitute the type Object
with your super type):
List<Object> pets2 = List.of("foo", 9, "bar", 27, new HashSet<>());
Map<String, List<Object>> classNameToPet =
pets2.stream()
.collect(Collectors.groupingBy(obj -> obj.getClass().getSimpleName()));
classNameToPet.forEach((k, v) -> System.out.println(k " : " v));
Output
Integer : [9, 27]
String : [foo, bar]
HashSet : [[]]
Note :
The way you are using
forEach()
is not encouraged by the documentation, take a look at the code example provided in the paragraph "side-effects".If you need to determine the actual class of your objects in order to interact with them, that means your usage inheritance is wrong. If list
pets2
has a generic parameter let's sayAnymal
, then you don't have to discriminate between the subtypes ofAnymal
, but take advantage from the polymorphism.
CodePudding user response:
This would happen, if there are only two different classes in the list. Later objects with the same class as a previous on overwrite the previous one because the key is the same.
CodePudding user response:
When you are iterating over the pets2 list and adding them to the animals map (Map<String, Object>), the put operation just overwrites the already inserted value for that specific class.
Eg:
pets2 = [dog1, dog2, cat1, cat2]
// The final animals map as per your method will be
animals = [{Dog, dog2}, {Cat, cat2}]
So, to handle the case of multiple repetitions of the same class objects in the pets list, we can change the code as follows
Map<String, List<Object>> animals = new HashMap<>();
pets2.forEach(pet -> animals.computeIfAbsent(pet.getClass().getSimpleName(), p -> new ArrayList<>()).add(pet));