假設我有一個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更好的列表,我會很高興發現它。 –