Jak użyć lambda Java8 do sortowania strumienia w odwrotnej kolejności?

181

Używam java lambda do sortowania listy.

jak mogę to posortować w odwrotny sposób?

Widziałem ten post , ale chcę użyć java 8 lambda.

Oto mój kod (użyłem * -1) jako 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
źródło
Co rozumiesz przez „odwrotną kolejność”? Jeśli zastąpi -1 * answersię answerkolejność zmieni się odwrócić tego, co było z -1 * ....
dasblinkenlight
2
Strzec się! Cały kod sugeruje, że chcesz użyć forEachOrderedzamiastforEach
Holger
dlaczego? możesz wytłumaczyć?
Elad Benda2
1
Postępuj zgodnie z linkami. Mówiąc prosto forEachOrdered, jak sama nazwa wskazuje, dba o kolejność spotkań, która jest istotna, ponieważ chcesz pominąć pewną liczbę najnowszych plików, która opiera się na kolejności „sortowania według czasu modyfikacji” .
Holger,
1
Nieco późno chcę przyznać, że twoje zrozumienie, jak sortskip→ (nieuporządkowane) forEachpowinno działać, jest poprawne i że rzeczywiście zostało wdrożone, aby działało w ten sposób w dzisiejszych JRE, ale w 2015 r., Kiedy pojawiły się poprzednie komentarze, to rzeczywiście był problemem (jak można przeczytać w tym pytaniu ).
Holger

Odpowiedzi:

218

Możesz dostosować rozwiązanie, które podłączyłeś w Jak sortować ArrayList <Long> w Javie w malejącej kolejności? zawijając go w lambda:

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

zwróć uwagę, że f2 jest pierwszym argumentem Long.compare, a nie drugim, więc wynik zostanie odwrócony.

Adrian Leonhard
źródło
224
… LubComparator.comparingLong(File::lastModified).reversed()
Holger
3
@Holger Stream String, posiadające comparingLong(v->Long.valueOf(v)).reversed()wyrzuca błąd kompilacji: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Czemu?
Tiina,
3
@ Tiina: patrz Comparator.reversed () nie kompiluje się przy użyciu lambda . Zamiast tego możesz spróbować comparingLong(Long::valueOf).reversed(). LubCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger
@Holger dzięki za link. Ale Stuart „nie do końca jest pewien, dlaczego”. Byłem zdezorientowany, gdy zobaczyłem, że obie metody odnoszą się Tzamiast Object, co oznacza, że ​​typ obiektu nie powinien zostać utracony. Ale tak naprawdę jest. Właśnie o to się mylę.
Tiina,
3
@ Tiina: propagacja wsteczna typu docelowego nie działa. Jeśli początkowe wyrażenie łańcucha ma autonomiczny typ, działa w nim tak, jak przed wersją Java 8. Jak widać na przykładzie komparatora, przy użyciu odwołania do metody, tj. comparingLong(Long::valueOf).reversed()Działa, podobnie jak jawnie wpisane wyrażenie lambda działa comparingLong((String v) -> Long.valueOf(v)).reversed()działa. Stream.of("foo").mapToInt(s->s.length()).sum()Działa również , ponieważ "foo"zapewnia typ autonomiczny, podczas gdy Stream.of().mapToInt(s-> s.length()).sum()nie działa.
Holger
170

Jeśli elementy strumienia zostaną zaimplementowane, Comparablerozwiązanie stanie się prostsze:

 ...stream()
 .sorted(Comparator.reverseOrder())
Grigorij Kislin
źródło
3
lub...stream().max(Comparator.naturalOrder())
Philippe
1
Za najnowszy element w zestawie porównującym według daty.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini,
1
Co jeśli elementy nie są Comparable. Collections.reversenie ma takiego ograniczenia.
wilmol
63

Posługiwać się

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

Następnie

.forEach(item -> item.delete());
Vishnudev K.
źródło
3
Cóż, zapytał o strumienie, ale mimo to podoba mi się twoja odpowiedź.
Tim Büthe
To nie jest „funkcjonalny” sposób na zrobienie tego ... ma to wpływ uboczny !!
Programator
38

Możesz użyć odwołania do metody:

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

Alternatywnie do odwołania do metody możesz użyć wyrażenia lambda, więc argumentem porównania jest:

.sorted(comparing(file -> file.lastModified()).reversed());
iFederx
źródło
19

Alternatywny sposób udostępniania:

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
źródło
4

Można to łatwo zrobić za pomocą Java 8 i odwróconego komparatora .

Utworzyłem listę plików z katalogu, które wyświetlam nieposortowane, posortowane i posortowane odwrotnie za pomocą prostego komparatora do sortowania, a następnie wywołując na nim reverse (), aby uzyskać odwróconą wersję tego komparatora.

Zobacz kod poniżej:

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
źródło
3

Sortuj listę plików za pomocą java 8 kolekcji

Przykład korzystania z kolekcji i komparatora Java 8 do sortowania listy plików.

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
źródło
1

W prosty sposób, używając Komparatora i Kolekcji, możesz sortować jak poniżej w odwrotnej kolejności za pomocą 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
źródło
0

W przypadku sortowania wstecznego wystarczy zmienić kolejność x1, x2 w celu wywołania metody x1.compareTo (x2), wynik będzie odwrócony względem siebie

Domyślne zamówienie

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

Odwrotna kolejność

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