Sorting a list with stream.sorted() in Java
Solution 1
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
Solution 2
Use list.sort
instead:
list.sort((o1, o2) -> o1.getItem().getValue().compareTo(o2.getItem().getValue()));
and make it more succinct using Comparator.comparing
:
list.sort(Comparator.comparing(o -> o.getItem().getValue()));
After either of these, list
itself will be sorted.
Your issue is that
list.stream.sorted
returns the sorted data, it doesn't sort in place as you're expecting.
Solution 3
Java 8 provides different utility api methods to help us sort the streams better.
If your list is a list of Integers(or Double, Long, String etc.,) then you can simply sort the list with default comparators provided by java.
List<Integer> integerList = Arrays.asList(1, 4, 3, 4, 5);
Creating comparator on fly:
integerList.stream().sorted((i1, i2) -> i1.compareTo(i2)).forEach(System.out::println);
With default comparator provided by java 8 when no argument passed to sorted():
integerList.stream().sorted().forEach(System.out::println); //Natural order
If you want to sort the same list in reverse order:
integerList.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println); // Reverse Order
If your list is a list of user defined objects, then:
List<Person> personList = Arrays.asList(new Person(1000, "First", 25, 30000),
new Person(2000, "Second", 30, 45000),
new Person(3000, "Third", 35, 25000));
Creating comparator on fly:
personList.stream().sorted((p1, p2) -> ((Long)p1.getPersonId()).compareTo(p2.getPersonId()))
.forEach(person -> System.out.println(person.getName()));
Using Comparator.comparingLong() method(We have comparingDouble(), comparingInt() methods too):
personList.stream().sorted(Comparator.comparingLong(Person::getPersonId)).forEach(person -> System.out.println(person.getName()));
Using Comparator.comparing() method(Generic method which compares based on the getter method provided):
personList.stream().sorted(Comparator.comparing(Person::getPersonId)).forEach(person -> System.out.println(person.getName()));
We can do chaining too using thenComparing() method:
personList.stream().sorted(Comparator.comparing(Person::getPersonId).thenComparing(Person::getAge)).forEach(person -> System.out.println(person.getName())); //Sorting by person id and then by age.
Person class
public class Person {
private long personId;
private String name;
private int age;
private double salary;
public long getPersonId() {
return personId;
}
public void setPersonId(long personId) {
this.personId = personId;
}
public Person(long personId, String name, int age, double salary) {
this.personId = personId;
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
Solution 4
It seems to be working fine:
List<BigDecimal> list = Arrays.asList(new BigDecimal("24.455"), new BigDecimal("23.455"), new BigDecimal("28.455"), new BigDecimal("20.455"));
System.out.println("Unsorted list: " + list);
final List<BigDecimal> sortedList = list.stream().sorted((o1, o2) -> o1.compareTo(o2)).collect(Collectors.toList());
System.out.println("Sorted list: " + sortedList);
Example Input/Output
Unsorted list: [24.455, 23.455, 28.455, 20.455]
Sorted list: [20.455, 23.455, 24.455, 28.455]
Are you sure you are not verifying list instead of sortedList
[in above example] i.e. you are storing the result of stream()
in a new List
object and verifying that object?
Solution 5
sorting Integer using streamAPI
arr.stream()
.sorted((item1,item2)-> Integer.compare(item1.price, item2.price))
.forEach(item-> item.show());
//asc
System.out.println("--------------------");
//desc
arr.stream()
.sorted((item1,item2)-> item1.price<item2.price?1:-1)
.forEach(item->item.show());
Ivan C
Updated on August 13, 2021Comments
-
Ivan C over 2 years
I'm interested in sorting a list from a stream. This is the code I'm using:
list.stream() .sorted((o1, o2)->o1.getItem().getValue().compareTo(o2.getItem().getValue())) .collect(Collectors.toList());
Am I missing something? The list is not sorted afterward.
It should sort the lists according to the item with the lowest value.
for (int i = 0; i < list.size(); i++) { System.out.println("list " + (i+1)); print(list, i); }
And the print method:
public static void print(List<List> list, int i) { System.out.println(list.get(i).getItem().getValue()); }
-
Neuron about 6 years
list.sort(Comparator.comparing(o -> o.getItem().getValue()));
was new to me. Great! -
River over 5 yearsI feel like this answer is way too detailed for the question, and yet doesn't address the question at all. Consider using this answer in a self-answered Q/A instead.
-
kakabali over 5 yearsI also feel that this is the best and correct answer. using
Comparator.comparing*
is the way better and more JDK8 oriented approach -
jmizv almost 3 yearsLooks like you don't take advantage of any stream related code.
-
Gaurav over 2 yearsworks flawlessly!