Stream sort() method

Java Streams are a powerful feature introduced in Java 8, providing a modern, functional approach to processing collections of data. One of the common tasks when dealing with collections is sorting, and Java Streams make this easy and intuitive. Let’s explore how to use the sort() method in Java Streams to sort data effectively. By the end, you’ll know how to sort elements using various criteria and handle both primitive and custom objects.

1. Introduction to Java Streams and the sort() Method

Java Streams provides a declarative way to process data collections, enabling you to write concise, readable code. The sort() method is a powerful feature of the Stream API, allowing you to sort elements based on natural ordering or custom criteria.

The sort() method is used within a Stream pipeline and returns a new, sorted Stream without modifying the original collection.

2. Sorting Simple Data Types

Sorting simple data types like integers or strings in Java Streams is straightforward. For instance, let’s say you have a list of integers:

				
					List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 3);
List<Integer> sortedNumbers = numbers.stream()
                                      .sorted()
                                      .collect(Collectors.toList());
System.out.println("Sorted Numbers: " + sortedNumbers);

//Output: Sorted Numbers: [1, 2, 3, 5, 8]


				
			

Here, sorted() sorts the elements in natural ascending order. For strings, this will also work based on lexicographic ordering:

				
					List<String> names = Arrays.asList("John", "Anna", "Zara", "Mike");
List<String> sortedNames = names.stream()
                                 .sorted()
                                 .collect(Collectors.toList());
System.out.println("Sorted Names: " + sortedNames);

//Output: Sorted Names: [Anna, John, Mike, Zara]
				
			

3. Sorting Custom Objects

To sort custom objects, you need to provide a comparator to the sorted() method. Let’s say you have a Person class with name and age fields:

				
					class Person {
    private String name;
    private int age;

    // Constructor, getters, and toString() method
}

List<Person> people = Arrays.asList(
    new Person("John", 25),
    new Person("Anna", 34),
    new Person("Mike", 19)
);

List<Person> sortedByAge = people.stream()
                                 .sorted(Comparator.comparing(Person::getAge))
                                 .collect(Collectors.toList());
System.out.println("Sorted by Age: " + sortedByAge);

// Output: Sorted by Age: [Mike (19), John (25), Anna (34)]
				
			

In this example, we use Comparator.comparing() to sort by age.

4. Sorting with Multiple Criteria

You may want to sort by multiple fields, such as sorting by age and then by name. You can achieve this by chaining comparators with thenComparing():

				
					List<Person> sortedByAgeThenName = people.stream()
                                          .sorted(Comparator.comparing(Person::getAge)
                                                            .thenComparing(Person::getName))
                                          .collect(Collectors.toList());
System.out.println("Sorted by Age, then Name: " + sortedByAgeThenName);


//Output: Sorted by Age, then Name: [Mike (19), John (25), Anna (34)]
				
			

Here, the sort() method first sorts by age, and if two people have the same age, it then sorts by name.

5. Sorting in Reverse Order

To reverse the sort order, use Comparator.reverseOrder() for simple data types or reversed() for custom comparators:

				
					List<Integer> reversedNumbers = numbers.stream()
                                       .sorted(Comparator.reverseOrder())
                                       .collect(Collectors.toList());
System.out.println("Reversed Numbers: " + reversedNumbers);

				
			

For custom objects, reverse a specific comparator:

				
					List<Person> sortedByAgeDesc = people.stream()
                                     .sorted(Comparator.comparing(Person::getAge).reversed())
                                     .collect(Collectors.toList());
System.out.println("Sorted by Age Descending: " + sortedByAgeDesc);

				
			
 

6. Tips and Best Practices

  • Use Method References: When possible, use method references for better readability (e.g., Person::getAge instead of p -> p.getAge()).
  • Chain Comparators for Complex Sorting: Use thenComparing() for sorting with multiple criteria.
  • Performance Consideration: Sorting a Stream  sorted() is generally efficient, but be aware that sorting large datasets can be resource-intensive.
  • Sorting in Parallel: While Stream can be parallelized, be cautious with sorted() parallel streams as it might lead to unexpected behaviours. Always test for your specific case.

7. Conclusion

Java Streams provide a flexible and readable way to sort collections. Whether sorting simple data types or complex objects, the sort() method helps streamline your code, making it more declarative and concise. With the power of comparators, you can quickly sort by multiple criteria and even reverse order. Embrace Java Streams, and your sorting tasks will become enjoyable and efficient!