Functionaljava:排序任意类型的列表

时间:2014-09-15 09:41:29

标签: java-8 functional-java

我有一个非常简单的Java bean WatchedFile,它有一个fileName字段。

我想对fj.data.ListWatchedFile个对象进行排序,但我正在努力为列表的fj.Ord方法定义sort()。这就是我想出的:

protected List<WatchedFile> getWatchedFileList(String path) throws IOException {
    List<File> files = List.list(new File(path).listFiles());
    return files
            .map((file) -> new WatchedFile(file.getName(), false, file.length()))
            .sort(Ord.ord(new F<WatchedFile, F<WatchedFile, Ordering>>()
            {
                @Override
                public F<WatchedFile, Ordering> f(final WatchedFile watchedFile1)
                {
                    return new F<WatchedFile, Ordering>()
                    {
                        @Override
                        public Ordering f(final WatchedFile watchedFile2)
                        {
                            int compareResult = watchedFile1.fileName.compareTo(watchedFile2.fileName);
                            return (compareResult < 0 ? Ordering.LT :
                                    (compareResult > 0 ? Ordering.GT : Ordering.EQ));
                        }
                    };
                }
            }));
}

这太丑了!我确信有一种更好的实例化Ord对象的方法......可能会使用一些Java 8 magick?

1 个答案:

答案 0 :(得分:2)

protected List<WatchedFile> getWatchedFileList(String path) throws IOException {
    List<File> files = Arrays.asList(new File(path).listFiles());
    return files.stream()
        .map(file -> new WatchedFile(file.getName(), false, file.length()))
        .sorted((wf1, wf2)->wf1.fileName.compareTo(wf2.fileName))
        .collect(Collectors.toList());
}

建议您在班级public String getFileName()中使用WatchedFile方法。在这种情况下,您可以简单地说:

protected List<WatchedFile> getWatchedFileList(String path) throws IOException {
    List<File> files = Arrays.asList(new File(path).listFiles());
    return files.stream()
        .map(file -> new WatchedFile(file.getName(), false, file.length()))
        .sorted(Comparator.comparing(WatchedFile::getFileName))
        .collect(Collectors.toList());
}

并且,使用NIO2获取目录条目,它可能看起来像:

protected List<WatchedFile> getWatchedFileList(String path) throws IOException {
    try {
        return Files.list(Paths.get(path))
            .map(p -> new WatchedFile(p.toString(), false, fileSize(p)))
            .sorted(Comparator.comparing(WatchedFile::getFileName))
            .collect(Collectors.toList());
    } catch(UncheckedIOException ex) { throw ex.getCause(); }
}
private long fileSize(Path path) {
    try { return Files.size(path); }
    catch (IOException ex) { throw new UncheckedIOException(ex); }
}

如果您希望保留在“functional-java”API中,解决方案可能如下所示:

protected List<WatchedFile> getWatchedFileList(String path) throws IOException {
    List<File> files = List.list(new File(path).listFiles());
    return files
        .map(file -> new WatchedFile(file.getName(), false, file.length()))
        .sort(Ord.stringOrd.comap(wf -> wf.fileName));
}

关键是你不需要(不应该)重新实现方式,String进行比较。而是指定函数以获取要比较的属性值。与第二个代码示例中使用的Java 8工厂方法Comparator.comparing进行比较。