Sorting a list with stream.sorted() in Java

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());
}
0

9 Answers

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

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 thatlist.stream.sorted returns the sorted data, it doesn't sort in place as you're expecting.

1

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; }
}
2

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?

1

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());

This is a simple example :

List<String> citiesName = Arrays.asList( "Delhi","Mumbai","Chennai","Banglore","Kolkata");
System.out.println("Cities : "+citiesName);
List<String> sortedByName = citiesName.stream() .sorted((s1,s2)->s2.compareTo(s1)) .collect(Collectors.toList());
System.out.println("Sorted by Name : "+ sortedByName);

It may be possible that your IDE is not getting the jdk 1.8 or upper version to compile the code.

Set the Java version 1.8 for Your_Project > properties > Project Facets > Java version 1.8

This might help for people ending up here searching how to sort list alphabetically.

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SortService { public static void main(String[] args) { List<TestData> test = new ArrayList<>(); test.add(prepareTestData("Asmin",1)); test.add(prepareTestData("saurav",4)); test.add(prepareTestData("asmin",2)); test.add(prepareTestData("Saurav",3)); test.forEach(data-> System.out.println(data)); /** Output * TestData(name=Asmin, id=1) * TestData(name=saurav, id=4) * TestData(name=asmin, id=2) * TestData(name=Saurav, id=3) */ test.sort(Comparator.comparing(TestData::getName,String::compareToIgnoreCase)); test.forEach(data-> System.out.println(data)); /**Sorted Output * TestData(name=Asmin, id=1) * TestData(name=asmin, id=2) * TestData(name=saurav, id=4) * TestData(name=Saurav, id=3) */ } private static TestData prepareTestData(String name, int id){ TestData testData= new TestData(); testData.setId(id); testData.setName(name); return testData; }
}
@Getter
@Setter
@ToString
class TestData{ private String name; private int id;
}
1

Using Comparator:

List<Type> result = list .stream() .sorted(Comparator.comparing(Type::getValue)) .collect(Collectors.toList());
Collection<Map<Item, Integer>> itemCollection = basket.values();
Iterator<Map<Item, Integer>> itemIterator = itemCollection.stream().sorted(new TestComparator()).collect(Collectors.toList()).iterator();
package com.ie.util;
import com.ie.item.Item;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class TestComparator implements Comparator<Map<Item, Integer>> {
// comparator is used to sort the Items based on the price @Override public int compare(Map<Item, Integer> o1, Map<Item, Integer> o2) { // System.out.println("*** compare method will be called *****"); Item item1 = null; Item item2 = null; Set<Item> itemSet1 = o1.keySet(); Iterator<Item> itemIterator1 = itemSet1.iterator(); if(itemIterator1.hasNext()){ item1 = itemIterator1.next(); } Set<Item> itemSet2 = o2.keySet(); Iterator<Item> itemIterator2 = itemSet2.iterator(); if(itemIterator2.hasNext()){ item2 = itemIterator2.next(); } return -item1.getPrice().compareTo(item2.getPrice()); }
}

**** this is helpful to sort the nested map objects like Map> here i sorted based on the Item object price .

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like