假设我有一个List
的路径,并且我想减少它以使最少数量的file.mkdirs()
运行来重新创建整个体系结构。用于创建文件体系结构的mkdirs的最小数量
因此,来自:
[/ FOO,/富/酒吧,/富/酒吧/ COO,/富/酒吧/ coo2,/富/芭比,/ notFoo /东西]
我想到:
[/ notFoo /东西,/富/芭比/富/酒吧/首席运营官/富/酒吧/ coo2]
我做这个天真的方法是:
List<String> l_paths = Arrays.asList("/foo","/foo/bar", "/foo/bar/coo","/foo/barbie","/notFoo/something");
ArrayList<String> l_reducted = new ArrayList<>();
List<String> l_ordered = l_paths.stream().sorted((p1,p2) -> p2.compareTo(p1)).collect(Collectors.toList());
for(String l_string : l_ordered){
if(l_reducted.stream().noneMatch(e -> e.startsWith(l_string) && e.substring(l_string.length()).contains("/"))){
l_reducted.add(l_string);
}
}
System.out.println(l_reducted);
,或者对Java 8对恋人:
// java 8 style, way less readable IMO
BiFunction<List<String>, String, List<String>> myAccumulator = new BiFunction<List<String>, String, List<String>>() {
@Override
public List<String> apply(List<String> list, String string) {
if (list.stream().noneMatch(e -> e.startsWith(string) && e.substring(string.length()).contains("/"))) {
list.add(string);
}
return list;
}
};
System.out.println(l_paths.stream().sorted((p1, p2) -> p2.compareTo(p1))
.reduce(new ArrayList<>(),
myAccumulator,
(list1, list2) -> {
list2.stream().forEach(i -> myAccumulator.apply(list1, i));
return list1;
}));
但我敢确信,分裂在隔板上的每一条路径,并将其插入到树形结构类似于文件系统会更好(但我不擅长树木,所以我没有实现它),因为它会允许以我的方式访问节点和mkdir。
你认为哪个更好?免责声明:我不是真的在这里讨论关于过早优化,我只是对算法感兴趣,对于知识好奇。但是让我们说mkdir实际上是一个调用非常慢的web服务(它甚至不理解整个路径上的mkdirs),并且调用的数量很重要。而且我们也会假设我的集合中有数百万条路径,并且减少的计算复杂度也很重要。
你是否分析了它,看看你的程序是否比简单地调用每个路径的'mkdirs()'更快? –
@SteveSmith我还没有,因为它不是一个实际的生产瓶颈,只是我多次遇到这个问题,从不关心。今天,我决定“如果我照顾一次,该怎么办?”。如果这件事很重要,那么做这种事情的方法是什么?如何通过迭代列表的测试正确地减少我的列表?我在我的问题中增加了一个免责声明(但我想我可以在没有它的情况下解决这个问题) –
我没有时间和预算来运行基准测试来优化不是瓶颈的事情。但是,如果有一个优雅的(简短易读的)方法来减少比mkdirs更好的列表,我会很高兴发现它。 –