I want to take a set of objects (ObjectInstance
in this case), and I want to group them by one property, and have the resulting lists be sorted on another.
Set<ObjectInstance> beans = server.queryMBeans(null, null);
Map<String, List<String>> beansByDomain = beans.stream()
.collect(groupingBy( (ObjectInstance oi) -> oi.getObjectName().getDomain(),
mapping((ObjectInstance oi) -> oi.getObjectName().getCanonicalKeyPropertyListString(),
toList() )));
The above expression creates the correct data structure: a Map
where the keys are the domains of the ObjectInstance
objects, and the values are Lists of the property lists. What I want is to now sort the Lists, to make sure they are in alphabetical order. Is there some way to do this in the same expression?
One idea would be to add .sort()
right after .stream()
, but is that really guaranteed to work?
Surely you can sort the whole stream before collecting:
Map<String, List<String>> beansByDomain = beans.stream()
.map(ObjectInstance::getObjectName)
.sorted(Comparator.comparing(ObjectName::getCanonicalKeyPropertyListString))
.collect(groupingBy(ObjectName::getDomain,
mapping(ObjectName::getCanonicalKeyPropertyListString,
toList() )));
Note that I added the .map(ObjectInstance::getObjectName)
step as you don't need anything else from ObjectInstance
. This will work nicely, though I cannot predict whether it's faster than sorting each resulting list separately or not.
If you prefer the separate toSortingList()
collector (as in @JeanLogeart answer), it can be optimized like this:
public static <T extends Comparable<T>> Collector<T,?,List<T>> toSortedList() {
return collectingAndThen(toCollection(ArrayList::new),
(List<T> l) -> {l.sort(Comparator.naturalOrder()); return l;});
}
Here we explicitly collect to ArrayList
(toList()
does the same, but it's not guaranteed), then sort the resulting list in-place without additional copying (using stream().sorted().collect(toList())
you copy the whole list content at least twice). Also note that <T>
parameter must be declared as extends Comparable<T>
. Otherwise you can mistakenly use this collector for non-comparable type which would compile fine, but result in runtime error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With