Ciprian Oancea
Ciprian Oancea

Reputation: 119

Sort a stream descending number

I have a list that which looks like this: [3 : [Reasonable product ], 5 : [Great ]] I want to sort (using streams) this list by the number before :. The list it has to look like this: [5 : [Great ], 3 : [Reasonable product ]] My code looks like this: return ratingsForProduct.stream().sorted().collect(Collectors.toList()); I don't know how to use lambda function or what I have to put as parameter to sorted().

Upvotes: 2

Views: 6705

Answers (4)

user4910279
user4910279

Reputation:

I think it's inefficient to convert a string to an integer each time strings are compared.

Try this.

List<String> result = list.stream()
    .map(string -> new Object() {
        int key = Integer.valueOf(string.substring(0, string.indexOf(":")).trim());
        String value = string;
    })
    .sorted(Comparator.comparing(obj -> obj.key, Comparator.reverseOrder()))
    .map(obj -> obj.value)
    .collect(Collectors.toList());

or

List<String> result = list.stream()
    .map(string -> Map.entry(Integer.valueOf(string.substring(0, string.indexOf(":")).trim()), string))
    .sorted(Comparator.comparing(Entry::getKey, Comparator.reverseOrder()))
    .map(Entry::getValue)
    .collect(Collectors.toList());

Upvotes: 1

WJS
WJS

Reputation: 40034

List<String> list = new ArrayList<>(
        List.of("3 : [Reasonable product ]", "5 : [Great ]"));

The comparator simply parses the number at the start of the string until a space is encountered. This will work for any size number within the range of an integer. You can use a stream or Collections.sort();

Comparator<String> comp = Comparator.comparing(
        a -> Integer.valueOf(a.substring(0,a.indexOf(" "))),
        Comparator.reverseOrder());

list = list.stream().sorted(comp)
        .collect(Collectors.toList());

System.out.println(list);

prints

[5 : [Great ], 3 : [Reasonable product ]]

Upvotes: 1

Ryuzaki L
Ryuzaki L

Reputation: 40038

You can pass the custom Comparator to sort descending order by extracting integer from every string

List<String> sortedList = list.stream()
            .sorted(Comparator.<String>comparingInt(s->Integer.parseInt(s.split(":")[0].trim())).reversed())
            .collect(Collectors.toList());

or you can also use Collections.sort

Collections.sort(list,Comparator.<String>comparingInt(s->Integer.parseInt(s.split(":")[0].trim())).reversed());

Upvotes: 4

Michael Bianconi
Michael Bianconi

Reputation: 5232

If you can be sure of the format of list items, you can write your own comparator:

Collections.sort(ratingsForProduct, (a, b) -> {
    return Integer.parseInt(b.substring(0, b.indexOf(':'))) -
           Integer.parseInt(a.substring(0, a.indexOf(':')));
});

We use substring(0, indexOf(':')) instead of charAt(0) to handle values greater than 10. If you wanted to sort in ascending order, you would change the comparator to substract b from a (instead of a from b as it is currently).

Upvotes: 1

Related Questions