Як за допомогою лямбда Java8 сортувати потік у зворотному порядку?


181

Я використовую java lambda для сортування списку.

як я можу сортувати її зворотним способом?

Я бачив цю публікацію , але хочу використовувати 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());

Що ви маєте на увазі під "зворотним замовленням"? Якщо замінити -1 * answerз answer, порядок зміниться на протилежне , що це було з -1 * ....
dasblinkenlight

2
Остерігайся! Весь ваш код говорить про те, що ви хочете використовувати forEachOrderedзамістьforEach
Holger

чому так? ти можеш пояснити?
Elad Benda2

1
Перейдіть за посиланнями. Простіше кажучи, forEachOrderedяк випливає з назви, піклується про порядок зіткнення , яка має відношення , як ви хочете , щоб пропустити певну кількість нових файлів, які спираються на «відсортоване за часом модифікації» порядку .
Холгер

1
Трохи запізнюючись, я хочу визнати, що ваше розуміння того, як sortskip→ (не упорядковано) forEachмає працювати, є правильним і що воно реально реалізоване таким чином у сучасних ЄРП, але ще в 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)))
Хольгер

@Holger дякую за посилання. Але Стюарт "не зовсім впевнений, чому". Я був розгублений, коли побачив, як обидва способи посилаються 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такого обмеження не має.
wilmol

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

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 та використання зворотного компаратора .

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

Дивіться код нижче:

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

Сортування списку файлів за допомогою колекції 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

Простіше кажучи, використовуючи компаратор та колекцію, ви можете сортувати, як показано нижче, у порядку розвороту за допомогою 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

Для зворотного сортування просто змініть порядок 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 );
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.