Say I have a map (myMap) of String and Object - Map<String, K> K has properties Name, Date and Age
How do I get the count of each occurrences of K.name in myMap and store it in a new map? The new map would show K.Name as a key and the value would be the number of times it appeared in myMap
CodePudding user response:
First, change the name of your class to something other than K
. That letter is often used as an abbreviation of map “key”. So K
as the value in a map is confusing. Let’s use Person
instead.
record Person ( String name, LocalDate date , int age ) {}
Define and populate your map.
Map< String , Person > map = … ;
Collect all the values from the map, all the Person objects.
Collection< Person > personsMapped = map.values() ;
Get a distinct list of the Person
objects found in your map as values.
List< Person > personsDistinct = map.values().stream().distinct().toList() ;
Define a map for the resulting count.
Map< Person , Integer > results = new HashMap<>() ;
For each of those distinct persons, search the collection of values to count occurrences.
for( Person person : personsDistinct ) {
int count = personsMapped.filter( p -> p.equals( person ) ).count() ;
results.put( person , count ) ;
}
Similarly, if you want to map results by name of person, use name as the key. But beware of data collisions in coincidentally same names. Mapping by name fails if the names are not unique.
Map< String , Integer > results = new HashMap<>() ;
for( Person person : personsDistinct ) {
int count = personsMapped.filter( p -> p.equals( person ) ).count() ;
results.put( person.name() , count ) ;
}
Or perhaps your goal is to count occurrences of name across Person
objects where you expect coincidentally same names.
List< String > namesDistinct = map.values().stream().map( Person :: name ).distinct().toList() ;
Map< String , Integer > results = new HashMap<>();
for ( String nameDistinct : namesDistinct ) {
int count = map.values().filter( p -> p.name().equals( nameDistinct ) ).count() ;
results.put( nameDistinct , count ) ;
}
CodePudding user response:
Use Stream API to get the stream from the values of the input map Map<String, K>
and build the map using Collectors::groupingBy
and Collectors::counting
/ Collectors::summingInt
:
Map<String, K> inputMap = getData(); // some input data
Map<String, Long> nameFrequencyMap = inputMap.values() // Collection<K>
.stream()
.collect(Collectors.groupingBy(
K::getName,
Collectors.counting()
));
// or use another summingInt collector if integer result is desired
Map<String, Integer> nameFrequencyIntMap = inputMap.values() // Collection<K>
.stream()
.collect(Collectors.groupingBy(
K::getName,
Collectors.summingInt(k -> 1)
));