AdBlock Detected

It looks like you're using an ad-blocker!

Our team work realy hard to produce quality content on this website and we noticed you have ad-blocking enabled. Advertisements and advertising enable us to continue working and provide high-quality content.

sort list with stream

The handling of lists in Java, starting from Java 8, often involves the use of Streams. In this brief article, we will see how to sort lists with Stream in Java.

What is a Java Stream?

The Java Stream API, introduced in Java 8, allows us to process and perform operations on collections of objects. A Stream is a sequence of objects that supports various methods in a sequence to obtain the desired result.

How to sort a list with Stream in Java?

Within Java streams, we have the “sorted” interface that allows us to perform sorting on the stream.

Stream<T> sorted()

Here, “stream” is an interface and “T” is the type of object in our collection.

This method returns a stream consisting of the type of element in the stream, where applying “sorted” will apply natural sorting. If the elements of the stream cannot be compared (not implementing Comparable), a ClassCastException exception will be thrown.

Sorting a list of integers with Stream in Java

Let’s apply the “sorted” method to sort lists of integers. First, let’s create a list:

List<Integer> integers = List.of(11,2,19,3,4);

Now, let’s perform natural sorting and see the output:

integers.stream()
        .sorted()
        .forEach(System.out::println);

The result would be:

2
3
4
11
19

If desired, we can store the result in a new list:

List<Integer> sortedInteger = integers.stream()
        .sorted()
        .collect(Collectors.toList());

Sorting a list of integers in descending order

Using “sorted()” on a stream will sort our list in natural (ascending) order. To sort it in descending order, we need to use “Collections.reverseOrder()” as a parameter for “sorted”.

For example, let’s sort the following list of integers in descending order:

List<Integer> integers = List.of(11,2,19,3,4);

List<Integer> sortedInteger = integers.stream()
        .sorted(Collections.reverseOrder())
        .collect(Collectors.toList());

System.out.println(sortedInteger);

The result of the above execution would be:

[19,11,4,3,2]

Sorting a list of strings in a Java stream

When we want to sort a list of strings in Java, we can use “sorted()” which will sort the list lexicographically.

Let’s see an example:

List<String> stringList = List.of("Alba","Noel","Pablo","Alejandro");

Let’s execute the following command:

List<String> sortedList = list.stream().sorted().collect(Collectors.toList());

System.out.println(sortedList);

The “sorted” operation above will perform lexicographic sorting as follows:

[Alba,Alejandro,Noel,Pablo]

Similarly, let’s see how to sort a list of strings in reverse order.

Sorting a list of strings in descending order

Similar to sorting a list of integers in reverse order using “Collections.reverseOrder()”, we can apply the same function to our list of strings.

List<String> stringList = List.of("Alba","Noel","Pablo","Alejandro");

List<String> sortedList = list.stream().sorted(Collections.reverseOrder()).collect(Collectors.toList());

System.out.println(sortedList);

Sometimes, we may need to sort complex custom objects. Let’s see it in the following points.

Sorting custom objects with Java Stream

In the previous examples, we have used “Comparables” types, but what happens when we have custom objects? Well, we can use a Comparator within the sorted method.

Let’s see an example with a User object:

@Getter
@Setter
@AllArgsConstructor
public class User {
    
    private String name;
    private int age;

}

We have a list of User objects, and we want to sort that list by age in natural order. Let’s see an example:

List<User> userList = List.of(
        new User("Noel", 39), 
        new User("Pablo", 1), 
        new User("Gusi", 38));

List<User> sortedList = userList.stream()
        .sorted(Comparator.comparingInt(User::getAge))
        .collect(Collectors.toList());

sortedList.forEach(System.out::println);

When executed, the output will be:

User:[name: Pablo, age: 1]
User:[name: Gusi, age: 38]
User:[name: Noel, age: 39]

In the above example, we filtered the User objects by the age field using the Comparator class and the comparingInt method:

static <T> Comparator<T> comparingInt(ToIntFunction <T> keyExtractor)

Similar to previous cases, we can obtain the reversed result of the list by using reversed().

List<User> userList = List.of(
        new User("Noel", 39), 
        new User("Pablo", 1), 
        new User("Gusi", 38));

List<User> sortedList = userList.stream()
        .sorted(Comparator.comparingInt(User::getAge).reversed())
        .collect(Collectors.toList());

sortedList.forEach(System.out::println);

And obviously, the result will be the list of users in reverse order:

User:[name: Noel, age: 39]
User:[name: Gusi, age: 38]
User:[name: Pablo, age: 1]

As a side note, if two User objects have the same age(), they will be ordered based on their position in the list. If we want additional sorting criteria, we would need to create a custom comparator, which we’ll see in the next section.

Creating a Custom Comparator for use in Stream.sorted()

Sometimes, we may want to perform comparisons based on something more complex than just integers or strings.

For example, in the previous case, if two users have the same age, they are sorted based on their position in the list. But what if we want to take their names into account for such occasions?

Let’s see how we can create a custom Comparator to sort according to our needs.

Let’s start with the previous example:

List<User> userList = List.of(
        new User("Noel", 39), 
        new User("Pablo", 1), 
        new User("Gusi", 38));


Now, we’re going to create a method that compares the names if two users have the same age:

private Comparator<User> userComparator() {

  return new Comparator<User>() {
      @Override
      public int compare(User user1, User user2) {
          if(user1.getAge() == user2.getAge())
              return user1.getName().compareTo(user2.getName());
          else if(user1.getAge() > user2.getAge())
              return 1;
          else return -1;
      }
  };

}

In the above method, we have sorted the User objects by age and then by name when two users have the same age. Now, let’s apply the above method to the sorting code:

List<User> sortedList = userList.stream()
        .sorted(userComparator)
        .collect(Collectors.toList());

This way, our lambda function will have users sorted by age and

Conclusión

In this post, we have seen how we can sort lists with Stream in Java by using predefined Java functions and creating our own method for comparisons.

Understanding how Comparator works will help us create our own custom sorting implementations.

If you need more information, you can leave us a comment or send an email to refactorizando.web@gmail.com You can also contact us through our social media channels on Facebook or twitter and we will be happy to assist you!!

Leave a Reply

Your email address will not be published. Required fields are marked *