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

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.


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

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

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

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

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

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

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

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 );
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.