我在类的根目录中有一个目录的arraylist ArrayList<File> sources
,以及一个方法addNewSource
,用于在列表中添加新目录。
private void addNewSource(File src){
sources.add(src);
}
现在我需要添加一个新方法来检查新源是否是列表中现有目录的子目录。让我们假设arraylist有以下目录:
["D:\", "E:\", "F:\"]
现在我要添加两个新目录,一个"G:\"
和另一个"D:\Folder\"
。对于第一个,新方法应返回false
,对于第二个,新方法应返回true
。
我发现的简单解决方案:
转到父目录并检查它是否存在于列表中,直到我们到达根目录。它完成了我的工作,但是在处理大型列表(1000个目录)时需要花费大量时间,并且新目录位于1500个父目录中。
您是否拥有或知道任何更好和优化的解决方案,不会花费很长的处理时间。请没有外部图书馆。
答案 0 :(得分:1)
首先,请注意,您不需要查看每个部分&#39; src
的{{1}},以查看它是否包含在sources
中。相反,你可以做类似的事情:
ArrayList<File> sources = new ArrayList<>();
boolean addNewSourceToList(File src) throws IOException
{
Path newPath = src.toPath();
for(File f : sources)
{
if(newPath.startsWith(f.toPath()))
{
return true;
}
}
sources.add(src);
return false;
}
基本上,startsWith()
方法为我们进行逐个部分比较。
当然,每次调用该方法时,此算法仍需要查看sources
中的每个元素(在最坏的情况下)。因此,如果sources
包含1000个项目,则需要进行1000次startsWith()
次比较。
正如@Holger建议的那样,更好的方法是使用Set
代替List
。但是,Set.contains()
方法基于元素.equals()
,因为(File
或Path
)并不具有&的概念#39;子目录&#39;,我们需要做一些有点特别的事情:我们需要看看每个&#39;部分&#39; src
中有sources
。
Set<Path> sourcesSet = new HashSet<>();
boolean addNewSourceToSet(File src) throws IOException
{
Path newPath = src.toPath();
// See if contained exactly
if(sourcesSet.contains(newPath))
{
return true;
}
Path parent = newPath.getParent();
while(parent != null)
{
if(sourcesSet.contains(parent))
{
return true;
}
parent = parent.getParent();
}
sourcesSet.add(newPath);
return false;
}
如果我们可以假设src
包含的内容远远少于1000个,那么算法的运行速度会更快,因为它只会为contains()
的每个部分运行一次src
方法