Sorting a List with Stream.Sorted() in Java

Sorting a list with stream.sorted() in Java

This is not like Collections.sort() where the parameter reference gets sorted. In this case you just get a sorted stream that you need to collect and assign to another variable eventually:

List result = list.stream().sorted((o1, o2)->o1.getItem().getValue().
compareTo(o2.getItem().getValue())).
collect(Collectors.toList());

You've just missed to assign the result

Java sort list with streams first by length then alphabetically

If you need to sort first by description length and then by description (alphabetical order), then your first comparison is fine but you also need to add a second comparison by description.

You can stack a second comparison by using the method thenComparing(). It will perform the second comparison only for elements with same length. There is no need to implement a custom Comparator for this scenario.

public List<Article> sortAsc() {
removeNull();
return articles.stream()
.sorted(Comparator.comparingInt((Article a) -> a.getDescription().length())
.thenComparing(Article::getDescription))
.collect(Collectors.toList());
}

Java stream sorting elements of ListObject

You can use Comparator chaining to sort by height and then by age. Then use the map operator to map the names and finally joining collector to concatenate the names into a formatted string of your interest. Here's how it looks.

String sortedNames = persons.stream()
.sorted(Comparator.comparingDouble(Person::getHeight)
.thenComparingDouble(Person::getAge).reversed())
.map(Person::getName)
.collect(Collectors.joining(", "));

P.S. However, I don't see double as a good data type to represent the age of a person. An int would be a much better alternative IMO.

Update:

If you have int data type to represent the age of a person, then the comparator chain should look like below. Everything else remains intact.

Comparator.comparingDouble(Person::getHeight)
.thenComparingInt(Person::getAge).reversed()

Java 11 Stream to sort a list of object and add sequence based on sorting

It could be I don't understand the issue because your code example refers to unknown fields (referringDepartment, referralSeqNumber) and unknown classes (SIUInformation) but I'm guessing this is likely what you more or less need?

userInformations.stream()
.collect(Collectors.groupingBy(UserInformation::getUserDepartment))
.values()
.forEach(listForDepartment -> {
AtomicInteger x = new AtomicInteger(1);
listForDepartment.stream()
.sorted(Comparator.comparing(UserInformation::getCreatedDate))
.forEachOrdered(item -> item.setUserSeqNumber(String.valueOf(x.getAndIncrement())));
});

First you group the UserInformation objects by department (resulting in Map<String List<UserInformation>) and then you loop the values in the Map created by this action. You then sort the values by createdDate using sorted() (Date comparator is by default ascending) and you then start filling in the userSeqNumber according the order of the elements, restarting from 1 for every department in the map.

Note I use forEachOrdered instead of forEach as I explicitly want to document that the order matters, even though in this case, it won't break the code if forEach is used instead.

What is more efficient: sorted stream or sorting a list?

It is safe to say that two forms of sort will have the same complexity ... even without looking at the code. (If they didn't then one form would be severely broken!)

Looking at Java 8 source code for streams (specifically the internal class java.util.stream.SortedOps), the sorted() method adds a component to a stream pipeline that captures all of the stream elements into either an array or an ArrayList.

  • An array is used if and only if the pipeline assembly code can deduce the number of elements in the stream ahead of time.

  • Otherwise, an ArrayList is used to gather the elements to be sorted.

If an ArrayList is used, you incur the extra overhead of building / growing the list.

Then we return to two versions of the code:

List<Item> sortedItems = new ArrayList<>(items);
Collections.sort(sortedItems, itemComparator);

In this version, the ArrayList constructor copies the elements items to an appropriately sized array, and then Collections.sort does an in-place sort of that array. (This happens under the covers).

List<Item> sortedItems = items
.stream()
.sorted(itemComparator)
.collect(Collectors.toList());

In this version, as we have seen above, the code associated with sorted() either builds and sorts an array (equivalent to what happens above) or it builds the ArrayList the slow way. But on top of that, there are the overheads of stream the data from items and to the collector.

Overall (with the Java 8 implementation at least) code examination tells me that first version of the code cannot be slower than the second version, and in most (if not all) cases it will be faster. But as the list gets larger, the O(NlogN) sorting will tend to dominate the O(N) overheads of copying. That will mean that the relative difference between the two versions will get smaller.

If you really care, you should write a benchmark to test the actual difference with a specific implementation of Java, and a specific input dataset. (Or adapt @Eugene's benchmark!)

How to Sort List based on Inner Object's property in java 8

Comparator.nullsLast or Comparator.nullsFirst should be applied to handle possible null values in the compared items:

finalResponses.sort(Comparator.nullsLast(
Comparator.comparing(fr -> fr.getSource().getSourceId())
));

or like this:

finalResponses.sort(Comparator.comparing(
fr -> fr.getSource().getSourceId(),
Comparator.nullsLast(Comparator.naturalOrder())
));

Java sorting list by element property with stream()

The return statement can be as simple as:

return students.stream()
.sorted(Comparator.comparingDouble(Student::getAverage).reversed())
.collect(Collectors.toList());

Comparator.comparingInt(Student::getAverage) returns a comparator that compares student average fields (assuming getter), and reversed() reverses the natural order.

Java Stream sorted() to generic List

Try this.

catalog = catalog.stream()
.sorted(Comparator.comparing(a -> a.getUnitPrice() * a.getUnitsInStore()))
.collect(Collectors.toList());

You can also sort in reverse order.

catalog = catalog.stream()
.sorted(Comparator.comparing((Article a) -> a.getUnitPrice() * a.getUnitsInStore()).reversed())
.collect(Collectors.toList());


Related Topics



Leave a reply



Submit