如何使用Java8 lambda反向排序流?


180

我正在使用Java lambda对列表进行排序。

如何以相反的方式对其进行排序?

我看到了这篇文章,但是我想使用java 8 lambda。

这是我的代码(我用* -1)作为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());

“逆序”是什么意思?如果替换-1 * answeranswer,则顺序将变为与之相反的顺序-1 * ...
dasblinkenlight

2
谨防!您的所有代码都建议您使用forEachOrdered而不是forEach
Holger 2015年

这是为什么?你可以解释吗?
Elad Benda2 2015年

1
按照链接。简而言之,forEachOrdered顾名思义,您关心的是遇到顺序,因为您要跳过一定数量的最新文件,而这些文件取决于“按修改时间排序”的顺序
Holger 2015年

1
有点晚了,我要感谢您的理解如何sort→交通skip→交通(无序)forEach应该工作,是正确的,它是能够实现这样的工作方式在当今的JRE,但早在2015年,当先前的评论意见,它确实是一个问题(您可能会在本问题中读到)。
Holger

Answers:


218

您可以调整在Java中如何以降序对ArrayList <Long>进行排序中链接的解决方案通过将其包装在lambda中:

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

请注意,f2是的第一个参数Long.compare,而不是第二个,因此结果将相反。


224
…或Comparator.comparingLong(File::lastModified).reversed()
Holger 2015年

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()不使用lambda进行编译。您可以尝试comparingLong(Long::valueOf).reversed()代替。或Collections.reverseOrder(comparingLong(v->Long.valueOf(v)))
Holger

@Holger感谢您的链接。但是斯图尔特“并不完全确定为什么”。当我看到两个方法都引用T而不是时Object,我感到很困惑,这意味着对象类型不应该丢失。但实际上是。那就是我的困惑。
蒂娜

3
@Tiina:这是目标类型的反向传播不起作用。如果链的初始表达式具有独立类型,则它像在Java 8之前一样在链中起作用。如比较器示例所示,使用方法引用即comparingLong(Long::valueOf).reversed()有效,同样,显式类型的lambda表达式工程comparingLong((String v) -> Long.valueOf(v)).reversed()作品。也Stream.of("foo").mapToInt(s->s.length()).sum()可以使用,因为会"foo"提供独立类型,而会Stream.of().mapToInt(s-> s.length()).sum()失败。
Holger

170

如果您的流元素实现,Comparable那么解决方案将变得更加简单:

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

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

1
对于按日期进行比较的集合中的最新元素.stream().max(Comparator.comparing(Clazz::getDate))
Marco Pelegrini,

1
如果元素不是,该怎么办ComparableCollections.reverse没有这样的限制。
wilmol

63

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

然后

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

3
好吧,他问了有关流的问题,但是我还是喜欢你的回答。
蒂姆·布斯(TimBüthe)2016年

这不是“功能性”的操作方式……有副作用!!
程序员

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

在方法引用的替代方法中,可以使用lambda表达式,因此compare的参数变为:

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

数据中心

List<Animal> animals = this.service.findAll();
animals = animals.stream().sorted(Comparator.comparing(Animal::getName).reversed()).collect(Collectors.toList());

4

使用Java 8和使用反向Comparator可以轻松完成此操作。

我已经从目录中创建了一个文件列表,我使用一个简单的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());
        }
    }
}

3

使用Java 8 Collections排序文件列表

示例如何使用Collections和Comparator 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 );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.