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
Java - Removing Duplicates in an Arraylist
Running a Java Program from Another Java Program
How Is This Private Variable Accessible
How to Use Parameters, Request and Session Objects Present in Actioncontext
How to Print Escape Characters in Java
Are Non-Capturing Groups Redundant
How to Use Mockito When We Cannot Pass a Mock Object to an Instance of a Class
Java - Convert Image to Base64
How to Pause and Resume a Thread in Java from Another Thread
How to Do a Fractional Power on Bigdecimal in Java
Sending the Same But Modifed Object Over Objectoutputstream
Persistent Httpurlconnection in Java
How Does Memory Reordering Help Processors and Compilers