Wie verwende ich ein Java8-Lambda, um einen Stream in umgekehrter Reihenfolge zu sortieren?

180

Ich benutze Java Lambda, um eine Liste zu sortieren.

Wie kann ich es umgekehrt sortieren?

Ich habe diesen Beitrag gesehen , möchte aber Java 8 Lambda verwenden.

Hier ist mein Code (ich habe * -1 verwendet) als 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
quelle
Was meinst du mit "umgekehrter Reihenfolge"? Wenn Sie ersetzen -1 * answermit answer, wird die Reihenfolge der umgekehrt ändern , was mit ihm war -1 * ....
Dasblinkenlight
2
In acht nehmen! Ihr ganzer Code schlägt vor, dass Sie forEachOrderedanstelle vonforEach
Holger
warum ist das so? können Sie erklären?
Elad Benda2
1
Folgen Sie den Links. Einfach gesagt, forEachOrderedkümmert sich, wie der Name schon sagt, um die Reihenfolge der Begegnungen, die relevant ist, da Sie eine bestimmte Anzahl der neuesten Dateien überspringen möchten, die von der Reihenfolge "Sortiert nach Änderungszeit" abhängt .
Holger
1
Ein bisschen spät möchte ich anerkennen, dass Ihr Verständnis davon, wie sortskip→ (ungeordnet) forEachfunktionieren sollte, richtig ist und dass es tatsächlich so implementiert ist, dass es in den heutigen JREs funktioniert, aber bereits 2015, als die vorherigen Kommentare abgegeben wurden, ist es so war in der Tat ein Problem (wie Sie in dieser Frage lesen können ).
Holger

Antworten:

216

Sie können die in Wie sortiere ich ArrayList <Long> in Java verknüpfte Lösung in absteigender Reihenfolge anpassen ? indem man es in ein Lambda einwickelt:

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

Beachten Sie, dass f2 das erste Argument von Long.compareund nicht das zweite ist, sodass das Ergebnis umgekehrt wird.

Adrian Leonhard
quelle
222
… OderComparator.comparingLong(File::lastModified).reversed()
Holger
3
@Holger Stream of String und mit comparingLong(v->Long.valueOf(v)).reversed()Kompilierungsfehlern : java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Warum?
Tiina
3
@Tiina: siehe Comparator.reversed () kompiliert nicht mit Lambda . Sie können es comparingLong(Long::valueOf).reversed()stattdessen versuchen . OderCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger
@ Holger danke für den Link. Aber der Stuart "nicht ganz sicher warum". Ich war verwirrt , wenn ich beiden Methoden sah beziehen Tstatt Object, was bedeutet , der Objekttyp sollte nicht verloren gehen. Aber eigentlich ist es das. Darüber bin ich verwirrt.
Tiina
3
@Tiina: es ist die Rückausbreitung des Zieltypen , die nicht funktioniert. Wenn der anfängliche Ausdruck Ihrer Kette einen eigenständigen Typ hat, durchläuft er die Kette wie vor Java 8. Wie Sie im Vergleichsbeispiel sehen können, verwendet eine Methodenreferenz, dh comparingLong(Long::valueOf).reversed()funktioniert, ebenfalls einen explizit typisierten Lambda-Ausdruck funktioniert comparingLong((String v) -> Long.valueOf(v)).reversed()funktioniert. Funktioniert auch Stream.of("foo").mapToInt(s->s.length()).sum(), da das "foo"den eigenständigen Typ bereitstellt, während dies Stream.of().mapToInt(s-> s.length()).sum()fehlschlägt.
Holger
170

Wenn Ihre Stream-Elemente implementiert werden, Comparablewird die Lösung einfacher:

 ...stream()
 .sorted(Comparator.reverseOrder())
Grigory Kislin
quelle
3
oder...stream().max(Comparator.naturalOrder())
Philippe
1
Für das neueste Element in einer Sammlung nach Datum vergleichen.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini
1
Was passiert , wenn die Elemente nicht Comparable. Collections.reversehat keine solche Einschränkung.
Wilmol
62

Verwenden

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

Dann

.forEach(item -> item.delete());
Vishnudev K.
quelle
3
Nun, er hat nach Streams gefragt, aber ich mag Ihre Antwort trotzdem.
Tim Büthe
Dies ist keine "funktionale" Art, es zu tun ... es hat Nebenwirkungen !!
Programmierer
37

Sie können eine Methodenreferenz verwenden:

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

Alternativ zur Methodenreferenz können Sie einen Lambda-Ausdruck verwenden, sodass das Argument des Vergleichs zu:

.sorted(comparing(file -> file.lastModified()).reversed());
iFederx
quelle
18

Alternative Wege teilen:

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
quelle
4

Dies kann leicht mit Java 8 und einem umgekehrten Komparator durchgeführt werden .

Ich habe eine Liste von Dateien aus einem Verzeichnis erstellt, die ich mit einem einfachen Komparator für die Sortierung unsortiert, sortiert und umgekehrt sortiert anzeige und dann reversed () aufrufe, um die umgekehrte Version dieses Komparators zu erhalten.

Siehe Code unten:

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
quelle
3

Sortieren Sie die Dateiliste mit Java 8 Collections

Beispiel für die Verwendung von Collections and Comparator Java 8 zum Sortieren einer Dateiliste.

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
quelle
1

Mit Comparator und Collection können Sie mit JAVA 8 ganz einfach in umgekehrter Reihenfolge sortieren

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

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

Für die umgekehrte Sortierung ändern Sie einfach die Reihenfolge von x1, x2, um die Methode x1.compareTo (x2) aufzurufen. Das Ergebnis ist umgekehrt

Standardreihenfolge

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

Umgekehrte Reihenfolge

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