给定一组无序的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
是否是另一个人的祖先。
答案 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来轻松解决这个问题;我只是不确定你想要它的表现。