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 sort→ skip→ (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.