¿Cómo utilizar un lambda Java8 para ordenar una secuencia en orden inverso?


181

Estoy usando Java Lambda para ordenar una lista.

¿Cómo puedo ordenarlo de forma inversa?

Vi esta publicación , pero quiero usar java 8 lambda.

Aquí está mi código (usé * -1) como un 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());

¿Qué quieres decir con "orden inverso"? Si reemplaza -1 * answercon answer, el orden cambiará a reverso de lo que era -1 * ....
dasblinkenlight

2
¡Tener cuidado! Todo su código sugiere que desea usar en forEachOrderedlugar deforEach
Holger

¿porqué es eso? ¿puedes explicar?
Elad Benda2

1
Sigue los enlaces. Simplemente dicho, forEachOrderedcomo su nombre indica, se preocupa por fin encuentro que es relevante ya que desea omitir un cierto número de nuevos archivos que se basa en la “ordenados por fecha de modificación” fin .
Holger

1
Un poco tarde, quiero reconocer que su comprensión de cómo debería funcionar sortskip→ (sin ordenar) forEach, es correcta y que de hecho se implementa para funcionar de esta manera en los JRE de hoy, pero en 2015, cuando se hicieron los comentarios anteriores, fue de hecho un problema (como puede leer en esta pregunta ).
Holger

Respuestas:


218

Puede adaptar la solución que vinculó en Cómo ordenar ArrayList <Long> en Java en orden decreciente? envolviéndolo en una lambda:

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

tenga en cuenta que f2 es el primer argumento de Long.compare, no el segundo, por lo que el resultado se revertirá.


224
... oComparator.comparingLong(File::lastModified).reversed()
Holger

3
@Holger Arroyo de cuerdas, y con comparingLong(v->Long.valueOf(v)).reversed()lanza error de compilación: java.lang.valueOf(java.lang.String) cannot be used on java.lang.valueOf(java.lang.Object). ¿Por qué?
Tiina

3
@Tiina: consulte Comparator.reversed () no se compila con lambda . Puedes intentarlo en su comparingLong(Long::valueOf).reversed()lugar. OCollections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger,

@Holger gracias por el enlace. Pero el Stuart "no está completamente seguro de por qué". Estaba confundido cuando vi a ambos métodos referirse en Tlugar de Object, lo que significa que el tipo de objeto no debería perderse. Pero en realidad lo es. Eso es lo que me confunde.
Tiina

3
@Tiina: es la propagación hacia atrás del tipo de destino que no funciona. Si la expresión inicial de su cadena tiene un tipo autónomo, funciona a través de la cadena como lo hizo antes de Java 8. Como puede ver con el ejemplo del comparador, utilizando una referencia de método, es decir comparingLong(Long::valueOf).reversed(), funciona, asimismo, una expresión lambda de tipo explícito trabajos comparingLong((String v) -> Long.valueOf(v)).reversed()trabajos También Stream.of("foo").mapToInt(s->s.length()).sum()funciona, ya que "foo"proporciona el tipo independiente, mientras que Stream.of().mapToInt(s-> s.length()).sum()falla.
Holger

170

Si sus elementos de secuencia se implementan Comparable, la solución se vuelve más simple:

 ...stream()
 .sorted(Comparator.reverseOrder())

3
o...stream().max(Comparator.naturalOrder())
Philippe

1
Para el elemento más reciente de una colección que compara por fecha.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini,

1
¿Qué pasa si los elementos no lo son Comparable? Collections.reverseno tiene tal restricción.
wilmol

63

Utilizar

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

Luego

.forEach(item -> item.delete());

3
Bueno, él preguntó por las transmisiones, pero no obstante, me gusta tu respuesta.
Tim Büthe

Esta no es una forma "funcional" de hacerlo ... ¡tiene efectos secundarios!
Programador

38

Puede usar una referencia de método:

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

Como alternativa a la referencia de método, puede usar una expresión lambda, por lo que el argumento de comparación se convierte en:

.sorted(comparing(file -> file.lastModified()).reversed());

19

Forma alternativa de compartir:

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

Esto se puede hacer fácilmente utilizando Java 8 y el uso de un comparador invertido .

He creado una lista de archivos a partir de un directorio, que visualizo sin clasificar, ordenados y ordenados inversamente usando un Comparador simple para la clasificación y luego invocando invertido () para obtener la versión inversa de ese Comparador.

Ver código a continuación:

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

Ordenar la lista de archivos con java 8 Collections

Ejemplo de cómo usar Colecciones y Comparator Java 8 para ordenar una lista de archivos.

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

En simple, utilizando Comparador y la colección se puede ordenar como a continuación en la inversión para el uso de 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

Para la clasificación inversa, simplemente cambie el orden de x1, x2 para llamar al método x1.compareTo (x2), el resultado será inverso entre sí

Orden predeterminada

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

Orden inverso

List<String> reverseSortedByName = citiesName.stream().sorted((s1,s2)->s2.compareTo(s1)).collect(Collectors.toList());
System.out.println("Reverse Sorted by Name : "+ reverseSortedByName );
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.