【问题标题】:Functionaljava: sorting a list of arbitrary typesFunctionaljava:对任意类型的列表进行排序
【发布时间】:2014-11-08 19:15:22
【问题描述】:

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

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

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 魔术?

【问题讨论】:

    标签: java-8 functional-java


    【解决方案1】:
    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());
    }
    

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

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

    如果您想留在“功能-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));
    }
    

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

    【讨论】:

    • 你可以做相当于问题代码“利用一些 Java 8 魔法”的代码:.sort(Ord.ord(a-&gt; b-&gt; Ord.stringOrd.compare(a.fileName, b.fileName))),但与替代方案相比,它仍然很丑……
    • 这很棒,Ord.stringOrd.comap() 正是我想要的。我还将尝试根据 Java 8 的特性重新评估对功能性java 的需求。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 2023-03-23
    • 1970-01-01
    • 2020-02-23
    • 1970-01-01
    • 2018-11-01
    相关资源
    最近更新 更多