284

I'm using a Java lambda to sort a list.

How can I sort it in a reverse way?

I saw How to sort ArrayList<Long> in decreasing order?, but I want to use a Java 8 lambda.

Here is my code (I used * -1) as a hack:

Arrays.asList(files).stream()
    .filter(file -> isNameLikeBaseLine(file, baseLineFile.getName()))
    .sorted(new Comparator<File>() {
        public int compare(File o1, File o2) {
            int answer;
            if (o1.lastModified() == o2.lastModified()) {
                answer = 0;
            } else if (o1.lastModified() > o2.lastModified()) {
                answer = 1;
            } else {
                answer = -1;
            }
            return -1 * answer;
        }
    })
    .skip(numOfNewestToLeave)
    .forEach(item -> item.delete());
6
  • What do you mean by "reverse order"? If you replace -1 * answer with answer, the order will change to reverse of what it was with -1 * .... Commented Feb 19, 2015 at 13:11
  • 2
    Beware! All of your code suggests that you want to use forEachOrdered instead of forEach Commented Feb 19, 2015 at 20:52
  • why is that? can you explain? Commented Feb 20, 2015 at 16:40
  • 1
    Follow the links. Simply said, forEachOrdered, as the name suggests, cares about encounter order which is relevant as you want to skip a certain number of newest files which relies on the “sorted by modification time” order. Commented Feb 20, 2015 at 17:20
  • 1
    A bit late, I want to acknowledge that your understanding of how sortskip→(unordered)forEach should work, is correct and that it is indeed implemented to work this way in today’s JREs, but back in 2015, when the previous comments were made, it was indeed an issue (as you may read in this question). Commented May 8, 2017 at 11:00

13 Answers 13

312

You can adapt the solution you linked in How to sort ArrayList<Long> in Java in decreasing order? by wrapping it in a lambda:

.sorted((f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified())

note that f2 is the first argument of Long.compare, not the second, so the result will be reversed.

Sign up to request clarification or add additional context in comments.

9 Comments

… or Comparator.comparingLong(File::lastModified).reversed()
@Holger Stream of String, and having comparingLong(v->Long.valueOf(v)).reversed() throws compiling error: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Why?
@Tiina: see Comparator.reversed() does not compile using lambda. You may try comparingLong(Long::valueOf).reversed() instead. Or Collections.reverseOrder(comparingLong(v->Long.valueOf(v)))
@Holger thanks for the link. But the Stuart "not entirely sure why". I was confused when i saw both methods refer T instead of Object, meaning the object type should not be lost. But actually it is. That is what I am confused about.
@Tiina: it’s the back-propagation of the target type which doesn’t work. If the initial expression of your chain has a stand-alone type, it works through the chain like it did before Java 8. As you can see with the comparator example, using a method reference, i.e. comparingLong(Long::valueOf).reversed() works, likewise an explicitly-typed lambda expression works comparingLong((String v) -> Long.valueOf(v)).reversed() works. Also Stream.of("foo").mapToInt(s->s.length()).sum() works, as the "foo" provides the stand-alone type whereas Stream.of().mapToInt(s-> s.length()).sum() fails.
|
310

If your stream elements implement Comparable then the solution becomes simpler:

 ...stream()
 .sorted(Comparator.reverseOrder())

3 Comments

or ...stream().max(Comparator.naturalOrder())
For the most recent element in a collection comparing by date .stream().max(Comparator.comparing(Clazz::getDate))
What if the elements are not Comparable. Collections.reverse does not have such a restriction.
86

Use

Comparator<File> comparator = Comparator.comparing(File::lastModified); 
Collections.sort(list, comparator.reversed());

Then

.forEach(item -> item.delete());

2 Comments

Well, he asked about streams, but I like your answer nonetheless.
This is not "functional" way of doing it... it's got side affects!!
65

You can use Comparator.comparing with a method reference to create a Comparator which sorts using the result of that method call, and reverse it using Comparator.reversed:

import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;

Arrays.asList(files).stream()
    .filter(file -> isNameLikeBaseLine(file, baseLineFile.getName()))
    .sorted(comparing(File::lastModified).reversed())
    .skip(numOfNewestToLeave)
    .forEach(item -> item.delete());

In alternative of method reference you can use a lambda expression, so the argument of comparing become:

.sorted(comparing(file -> file.lastModified()).reversed());

Comments

36

Alternative way sharing:

ASC

List<Animal> animals = this.service.findAll();
animals = animals.stream().sorted(Comparator.comparing(Animal::getName)).collect(Collectors.toList());

DESC

List<Animal> animals = this.service.findAll();
animals = animals.stream().sorted(Comparator.comparing(Animal::getName).reversed()).collect(Collectors.toList());

Comments

15

In simple, using Comparator and Collection you can sort like below in reversal order using JAVA 8

import java.util.Comparator;;
import java.util.stream.Collectors;

Arrays.asList(files).stream()
    .sorted(Comparator.comparing(File::getLastModified).reversed())
    .collect(Collectors.toList());

Make sure that, you are override the object with hashCode() and equals methods, otherwise the above code will not work.

Comments

5

This can easily be done using Java 8 and the use of a reversed Comparator.

I have created a list of files from a directory, which I display unsorted, sorted and reverse sorted using a simple Comparator for the sort and then calling reversed() on it to get the reversed version of that Comparator.

See code below:

package test;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class SortTest {
    public static void main(String... args) {
        File directory = new File("C:/Media");
        File[] files = directory.listFiles();
        List<File> filesList = Arrays.asList(files);

        Comparator<File> comparator = Comparator.comparingLong(File::lastModified);
        Comparator<File> reverseComparator = comparator.reversed();

        List<File> forwardOrder = filesList.stream().sorted(comparator).collect(Collectors.toList());
        List<File> reverseOrder = filesList.stream().sorted(reverseComparator).collect(Collectors.toList());

        System.out.println("*** Unsorted ***");
        filesList.forEach(SortTest::processFile);

        System.out.println("*** Sort ***");
        forwardOrder.forEach(SortTest::processFile);

        System.out.println("*** Reverse Sort ***");
        reverseOrder.forEach(SortTest::processFile);
    }

    private static void processFile(File file) {
        try {
            if (file.isFile()) {
                System.out.println(file.getCanonicalPath() + " - " + new Date(file.lastModified()));
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Comments

3

Sort file list with java 8 Collections

Example how to use Collections and Comparator Java 8 to sort a File list.

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ShortFile {

    public static void main(String[] args) {
        List<File> fileList = new ArrayList<>();
        fileList.add(new File("infoSE-201904270100.txt"));
        fileList.add(new File("infoSE-201904280301.txt"));
        fileList.add(new File("infoSE-201904280101.txt"));
        fileList.add(new File("infoSE-201904270101.txt"));

        fileList.forEach(x -> System.out.println(x.getName()));
        Collections.sort(fileList, Comparator.comparing(File::getName).reversed());
        System.out.println("===========================================");
        fileList.forEach(x -> System.out.println(x.getName()));
    }
}

Comments

3

Instead of all these complications, this simple step should do the trick for reverse sorting using Lambda .sorted(Comparator.reverseOrder())

Arrays.asList(files).stream()
.filter(file -> isNameLikeBaseLine(file, baseLineFile.getName()))
.sorted(Comparator.reverseOrder()).skip(numOfNewestToLeave)
.forEach(item -> item.delete());

1 Comment

Its not clear, please explain it.
1

For reverse sorting just change the order of x1, x2 for calling the x1.compareTo(x2) method the result will be reverse to one another

Default order

List<String> sortedByName = citiesName.stream().sorted((s1,s2)->s1.compareTo(s2)).collect(Collectors.toList());
System.out.println("Sorted by Name : "+ sortedByName);

Reverse Order

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );

Comments

1

You can define your Comparator with your own logic like this;

private static final Comparator<UserResource> sortByLastLogin = (c1, c2) -> {
    if (Objects.isNull(c1.getLastLoggedin())) {
        return -1;
    } else if (Objects.isNull(c2.getLastLoggedin())) {
        return 1;
    }
    return c1.getLastLoggedin().compareTo(c2.getLastLoggedin());
};   

And use it inside foreach as:

list.stream()
     .sorted(sortCredentialsByLastLogin.reversed())
     .collect(Collectors.toList());

Comments

1
    //sort Stream in reverse oreder with using Lambda Expressrion.

    List<String> list = Arrays.asList("Ram","Rahul","Ravi","Vishal","Vaibhav","Rohit","Harit","Raghav","Shubhan");
    List<String> sortedListLambda = list.stream().sorted((x,y)->y.compareTo(x)).collect(Collectors.toList());
    System.out.println(sortedListLambda);

Comments

-1

If you want to sort by Object's date type property then

public class Visit implements Serializable, Comparable<Visit>{
private static final long serialVersionUID = 4976278839883192037L;

private Date dos;

public Date getDos() {
    return dos;
}

public void setDos(Date dos) {
    this.dos = dos;
}

@Override
public int compareTo(Visit visit) {
    return this.getDos().compareTo(visit.getDos());
}

}

List<Visit> visits = getResults();//Method making the list
Collections.sort(visits, Collections.reverseOrder());//Reverser order

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.