Need to sort elements in a Stream sequence? That's the easiest thing in the world to do.
In this guide, I'll show you how to do it.
Even better: I'll sweeten the offer by using data that resembles what you'd see in a real-world business application. Other writers can show you how to do that foo::bar stuff.
Anyhoo, let's get started.
The CRM App
Let's say you're building a CRM app. It does the normal stuff that CRM apps do: tracks activities between sales reps and contacts.
Those activities get stored in a MongoDB database as documents. Each document persists info like the title of the activity as well as the type, outcome, location, start time, end time, notes, and the contact involved.
As it stands right now, if you retrieve all the documents from the activities collection, the resulting data set looks like the JSON dump at this link.
As you can see, we're not messing around here. You're going to be working with real-world data.
On the Java side, the Activity class with its related classes mimic the data set that you see above. You can see examples of those classes over on GitHub.
So you can just do a findAll() on that collection above and get a List of Java objects that represent that JSON output. Then, you can use a Java Stream to filter, find, and map as you see fit.
That's what you'll do in this guide.
And, yes, you could do that kind of stuff with MongoDB aggregations. But you're not here to learn about aggregations are you?
Taking It to the Next Level
In this guide, I'll pick up where I left off in the previous guide.
If you read it, you'll know that the requirements involved getting a distinct set of location names from the activities collection.
So you ended up with this code:
String names = activities .stream() .filter(activity -> !StringUtils.isBlank(activity.getLocation())) .map(Activity::getLocation) .distinct() .collect(Collectors.joining("\n"));
And that gave you this result:
Bruno's That Italian Joynt Banana Joe's Izzy's Loony's
Pretty good. But it's not alphabetized, is it?
Fortunately, it's a breeze to fix that problem.
Here's how to sort the returned elements alphabetically:
String names = activities .stream() .filter(activity -> !StringUtils.isBlank(activity.getLocation())) .map(Activity::getLocation) .distinct() .sorted() .collect(Collectors.joining("\n"));
The only change there from the previous code is the sorted() method after distinct().
That method does exactly what it sounds like it does. It sorts the elements returned from previous operation based on their natural order. In this case, the natural order is alphabetical because the elements are String objects.
So how would you sort more complex objects? That's easy, too.
The sorted() method is overloaded. You can use it with a Comparator as well.
Or you can implement Comparable on the complex object and use the sorted() method with no parameters.
It all depends on how you roll.
But getting back to the solution above, if you run that code with the dataset I referenced earlier, you'll see this result:
Banana Joe's Bruno's Izzy's Loony's That Italian Joynt
There you go. Now all the location names are sorted alphabetically.
Wrapping It Up
Wasn't that easy?
Now it's time for you to start using sorted() in your own Stream operation chains. Then you can return results in a predictable order.
Just make sure you have fun!
Photo by from