在一组Java File对象中查找唯一的超级目录

时间:2014-07-29 18:01:56

标签: java file

给定一组无序的Java File对象,我想要消除集合中其他Files的所有子目录(或子目录中的文件)。例如,给定:

File("/john/paul/george/ringo")
File("/foo/bar/baz")
File("/foo/bar/elvis")
File("/john/paul")
File("/john/jacob")
File("/foo/bar/baz/qux/quux")
File("/john/")
File("/foo/bar/")

该集合应减少为:

File("/foo/bar/")
File("/john/")

我可以想象基于转换为带有File.getAbsolutePath()的字符串和排序(可能先按长度排序,然后按字典顺序排列)来拼凑一些东西,但这肯定是一个已解决的问题,或者至少有人必须已经有书面的实用方法比如确定一个File是否是另一个人的祖先。

1 个答案:

答案 0 :(得分:0)

我不是最优秀的程序员,但我的目标就在这里。这涉及到相当多的递归。

class UniqueDirectories {
    private final Map<String, UniqueDirectories> directories = new HashMap<String, UniqueDirectories>();
    private boolean locked = false;

    public UniqueDirectories() {}

    private UniqueDirectories(boolean locked) {
        this.locked = locked;
    }

    public boolean add(String path) {
        if (path == null)
            return false;
        if (path.isEmpty())
            return false;
        if (locked)
            return false;

        String[] tokens = path.split("(?<!^)[/\\\\]", 2);
        UniqueDirectories existingDirectory = directories.get(tokens[0]);

        if (existingDirectory == null) {
            if (tokens.length < 2 || tokens[1].isEmpty()) {
                directories.put(tokens[0], new UniqueDirectories(true));

                return true;
            } else {
                UniqueDirectories newDirectory = new UniqueDirectories(false);
                directories.put(tokens[0], newDirectory);

                return newDirectory.add(tokens[1]);
            }
        } else if (tokens.length >= 2 && !tokens[1].isEmpty()) {
            return existingDirectory.add(tokens[1]);
        } else {
            directories.put(tokens[0], new UniqueDirectories(true));

            return true;
        }
    }

    public List<String> toList(char delimiter) {
        List<String> list = new ArrayList<String>();

        for (Map.Entry<String, UniqueDirectories> entry : directories.entrySet()) {
            if (entry.getValue().directories.size() == 0) {
                list.add(entry.getKey());
            } else {
                for (String subdirectory : entry.getValue().toList(delimiter)) {
                    list.add(entry.getKey() + delimiter + subdirectory);
                }
            }
        }

        return list;
    }

    public static void main(String[] args) {
        String[] testPaths = {
                "/john/paul/george/ringo",
                "/foo/bar/baz",
                "/foo/bar/elvis",
                "/john/paul",
                "/john/jacob",
                "/foo/bar/baz/qux/quux",
                "/john/",
                "/foo/bar/"
        };

        UniqueDirectories directories = new UniqueDirectories();

        for (String path : testPaths) {
            directories.add(path);
        }

        System.out.println(directories.toList('/'));
    }
}

对于缺乏评论感到抱歉。太懒了回去做,但至少代码相对较短。我还没有通过严格的测试(只使用你提供的那些),所以你可能想要使用更多的测试用例。

最值得注意的是一致性。如果使用分隔符启动路径,则所有路径都应以1开头。相反,如果一条路径不以分隔符开头,则其余路径也不应该。否则,它们将被视为不同的路径。你可以通过删除正则表达式中的lookbehind来轻松解决这个问题;我只是不确定你想要它的表现。