Как использовать лямбду Java8 для сортировки потока в обратном порядке?

181

Я использую Java-лямбду для сортировки списка.

как я могу отсортировать его в обратном порядке?

Я видел этот пост , но я хочу использовать Java 8 лямбда.

Вот мой код (я использовал * -1) как взломать

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
источник
Что вы подразумеваете под «обратным порядком»? Если вы замените -1 * answerна answer, порядок изменится на обратный -1 * ....
dasblinkenlight
2
Осторожно! Весь ваш код предполагает, что вы хотите использовать forEachOrderedвместоforEach
Хольгер
это почему? Вы можете объяснить?
Elad Benda2
1
Перейдите по ссылкам. Проще говоря, forEachOrderedкак следует из названия, заботится о порядке столкновения , которая имеет отношение , как вы хотите , чтобы пропустить определенное количество новых файлов, опирающиеся на «отсортированный по времени модификации» порядка .
Хольгер
1
Немного поздно, я хочу признать, что ваше понимание того, как sortskip→ (неупорядоченный) forEachдолжен работать, правильно и что оно действительно реализовано для работы таким образом в сегодняшних JRE, но еще в 2015 году, когда были сделаны предыдущие комментарии, оно была действительно проблема (как вы можете прочитать в этом вопросе ).
Хольгер

Ответы:

218

Вы можете адаптировать решение, которое вы связали в Как отсортировать ArrayList <Long> в Java в порядке убывания? завернув его в лямбду:

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

обратите внимание, что f2 является первым аргументом Long.compare, а не вторым, поэтому результат будет обратным.

Адриан Леонард
источник
224
… ИлиComparator.comparingLong(File::lastModified).reversed()
Хольгер
3
@Holger Поток строки, и с comparingLong(v->Long.valueOf(v)).reversed()бросками компиляции ошибка: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). Зачем?
Тийна
3
@Tiina: см. Comparator.reversed () не компилируется с использованием лямбды . Вы можете попробовать comparingLong(Long::valueOf).reversed()вместо этого. ИлиCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Хольгер
@ Хольгер спасибо за ссылку. Но Стюарт "не совсем уверен, почему". Я был сбит с толку, когда увидел, что оба метода ссылаются, Tа не Objectозначает, что тип объекта не должен быть потерян. Но на самом деле это так. Вот что меня смущает.
Тийна
3
@Tiina: это обратное распространение целевого типа, которое не работает. Если начальное выражение вашей цепочки имеет автономный тип, оно работает по цепочке, как это было до Java 8. Как вы можете видеть на примере компаратора, с использованием ссылки на метод, т. Е. comparingLong(Long::valueOf).reversed()Работает, аналогично лямбда-выражению с явной типизацией работает comparingLong((String v) -> Long.valueOf(v)).reversed()работает. Также Stream.of("foo").mapToInt(s->s.length()).sum()работает, так как "foo"обеспечивает автономный тип, тогда как Stream.of().mapToInt(s-> s.length()).sum()не работает.
Хольгер
170

Если ваши элементы потока реализуются, Comparableто решение становится проще:

 ...stream()
 .sorted(Comparator.reverseOrder())
Григорий Кислин
источник
3
или...stream().max(Comparator.naturalOrder())
Филипп
1
Для самого последнего элемента в коллекции, сравнивающей по дате.stream().max(Comparator.comparing(Clazz::getDate))
Марко Пелегрини
1
Что делать, если элементов нет Comparable. Collections.reverseне имеет такого ограничения.
Уилмол
63

использование

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

затем

.forEach(item -> item.delete());
Вишнудев К
источник
3
Ну, он спросил о потоках, но, тем не менее, мне нравится ваш ответ.
Тим Бюте
Это не "функциональный" способ сделать это ... у него есть побочные эффекты!
Программист
38

Вы можете использовать ссылку на метод:

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

В качестве альтернативы ссылки на метод вы можете использовать лямбда-выражение, поэтому аргументом сравнения становится:

.sorted(comparing(file -> file.lastModified()).reversed());
iFederx
источник
19

Альтернативный способ обмена:

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

Это легко сделать с помощью Java 8 и обратного компаратора .

Я создал список файлов из каталога, который я отображаю несортированными, отсортированными и отсортированными в обратном порядке, используя простой Comparator для сортировки, а затем вызывая reversed () для него, чтобы получить обратную версию этого Comparator.

Смотрите код ниже:

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
источник
3

Сортировка списка файлов с коллекциями java 8

Пример использования Коллекций и Компаратора Java 8 для сортировки списка файлов.

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

Проще говоря, используя Comparator и Collection, вы можете сортировать, как показано ниже, в обратном порядке, используя 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
источник
0

Для обратной сортировки просто измените порядок x1, x2 для вызова метода x1.compareTo (x2), результат будет обратным друг другу

Порядок по умолчанию

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

Обратный порядок

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );
Джимми
источник