Comment utiliser un lambda Java8 pour trier un flux dans l'ordre inverse?

181

J'utilise java lambda pour trier une liste.

comment puis-je le trier de manière inversée?

J'ai vu ce post , mais je veux utiliser java 8 lambda.

Voici mon code (j'ai utilisé * -1) comme un 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());
Elad Benda2
la source
Qu'entendez-vous par «ordre inverse»? Si vous remplacez -1 * answerpar answer, l'ordre changera pour inverser ce qu'il était avec -1 * ....
dasblinkenlight
2
Il faut se méfier! Tout votre code suggère que vous souhaitez utiliser à la forEachOrderedplace deforEach
Holger
pourquoi donc? peux-tu expliquer?
Elad Benda2
1
Suivez les liens. Simplement dit, forEachOrderedcomme son nom l' indique, soins sur ordre de rencontre qui est pertinent que vous voulez sauter un certain nombre de nouveaux fichiers qui repose sur le « trié par date de modification » ordre .
Holger
1
Un peu tard, je tiens à reconnaître que votre compréhension de la façon dont sortskip→ (non ordonné) forEachdevrait fonctionner, est correcte et qu'elle est effectivement implémentée pour fonctionner de cette manière dans les JRE d'aujourd'hui, mais en 2015, lorsque les commentaires précédents ont été faits, il était en effet un problème (comme vous pouvez le lire dans cette question ).
Holger

Réponses:

218

Vous pouvez adapter la solution que vous avez liée dans Comment trier ArrayList <Long> en Java par ordre décroissant? en l'enveloppant dans un lambda:

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

notez que f2 est le premier argument de Long.compare, pas le second, donc le résultat sera inversé.

Adrian Leonhard
la source
224
… OuComparator.comparingLong(File::lastModified).reversed()
Holger
3
@Holger flux de chaîne, et ayant comparingLong(v->Long.valueOf(v)).reversed()plaids la compilation d' erreur: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Pourquoi?
Tiina
3
@Tiina: voir Comparator.reversed () ne compile pas en utilisant lambda . Vous pouvez essayer à la comparingLong(Long::valueOf).reversed()place. OuCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger
@Holger merci pour le lien. Mais le Stuart "ne sait pas tout à fait pourquoi". J'étais confus quand j'ai vu les deux méthodes se référer Tau lieu de Object, ce qui signifie que le type d'objet ne devrait pas être perdu. Mais en fait c'est le cas. C'est de cela que je suis confus.
Tiina
3
@Tiina: c'est la rétro-propagation du type cible qui ne fonctionne pas. Si l'expression initiale de votre chaîne a un type autonome, elle fonctionne à travers la chaîne comme avant Java 8. Comme vous pouvez le voir avec l'exemple de comparaison, l'utilisation d'une référence de méthode, ie comparingLong(Long::valueOf).reversed()fonctionne, de même une expression lambda explicitement typée fonctionne comparingLong((String v) -> Long.valueOf(v)).reversed()fonctionne. Fonctionne également Stream.of("foo").mapToInt(s->s.length()).sum(), car le "foo"fournit le type autonome alors qu'il Stream.of().mapToInt(s-> s.length()).sum()échoue.
Holger
170

Si vos éléments de flux implémentent, Comparablela solution devient plus simple:

 ...stream()
 .sorted(Comparator.reverseOrder())
Grigory Kislin
la source
3
ou...stream().max(Comparator.naturalOrder())
Philippe
1
Pour l'élément le plus récent d'une collection comparée par date.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini
1
Et si les éléments ne le sont pas Comparable. Collections.reversen'a pas une telle restriction.
wilmol
63

Utilisation

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

ensuite

.forEach(item -> item.delete());
Vishnudev K
la source
3
Eh bien, il a posé des questions sur les flux, mais j'aime quand même votre réponse.
Tim Büthe
Ce n'est pas une façon "fonctionnelle" de le faire ... ça a des effets secondaires !!
Programmeur
38

Vous pouvez utiliser une référence de méthode:

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

En alternative à la référence de méthode, vous pouvez utiliser une expression lambda, donc l'argument de comparaison devient:

.sorted(comparing(file -> file.lastModified()).reversed());
iFederx
la source
19

Partage alternatif:

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());
Chang
la source
4

Cela peut facilement être fait en utilisant Java 8 et l'utilisation d'un comparateur inversé .

J'ai créé une liste de fichiers à partir d'un répertoire, que j'affiche non triés, triés et triés à l'envers à l'aide d'un simple comparateur pour le tri, puis en appelant reverse () dessus pour obtenir la version inversée de ce comparateur.

Voir le code ci-dessous:

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());
        }
    }
}
ManoDestra
la source
3

Trier la liste de fichiers avec les collections Java 8

Exemple d'utilisation de Collections et Comparator Java 8 pour trier une liste de fichiers.

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()));
    }
}
Jonathan Mendoza
la source
1

En simple, en utilisant Comparator et Collection, vous pouvez trier comme ci-dessous dans l' ordre inverse en utilisant JAVA 8

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

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

Pour le tri inversé, changez simplement l'ordre de x1, x2 pour appeler la méthode x1.compareTo (x2), le résultat sera inversé.

Ordre par défaut

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

Ordre inverse

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