I have an stream of objects as a parameter to a function(I can only consume the stream once).
Object has an string attribute called category.
I need a sorted list of categories.
I need to sort it based on number of occurences of each category.
If number of occurences are same, then lexicographically order the categories.
java8 stream grouping and sorting on aggregate sum
I basically need something like this but I don’t have the luxury of consuming the stream more than once.
Ex:
Data
{
object1 :{category:"category1"},
object2 :{category:"categoryB"},
object3 :{category:"categoryA"},
object4 :{category:"category1"},
object5 :{category:"categoryB"},
object6 :{category:"category1"},
object7 :{category:"categoryA"}
}
Output
List = {category1, categoryA, categoryB}
>Solution :
You can generate a Map of frequencies for each category of type Map<String,Long> (count by category).
Then create a stream over its entries and sort them (by Value, i.e. by count, and Key, i.e. lexicographically), extract the category from each entry and store the result into a list.
Assuming that you have the following domain type:
public class MyType {
private String category;
// getters
}
Method generating a sorted list of categories might be implemented like this:
public static List<String> getSortedCategories(Stream<MyType> stream) {
return stream.collect(Collectors.groupingBy(
MyType::getCategory,
Collectors.counting()
))
.entrySet().stream()
.sorted(
Map.Entry.<String, Long>comparingByValue()
.thenComparing(Map.Entry.comparingByKey())
)
.map(Map.Entry::getKey)
.toList();
}