深层次树状结构遍历的改进 查找硬盘中的 “java.exe”
来源:互联网 发布:解压缩数据错误 编辑:程序博客网 时间:2024/05/22 08:25
原文:http://www.yi-dao.com/works/model/sample/findFiles.htm
遍历深层次的树状结构。这里的例子是查找所有本地硬盘中的“java.exe”文件。
当向一个深层的目录寻找特定的文件时,很容易想到通过不断地迭代来遍历。
import java.io.File;
public class FileSearchTool {
public static void main(String[] args) {
String toFind = "java.exe";
File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++) {
searchList(roots[i], toFind);
}
}
public static void searchList(File file, String toFind) {
File[] files = file.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
searchList(file, toFind);
}
else if (files[i].getName().equals(toFind)) {
System.out.println(files[i].getAbsolutePath());
}
}
}
}
}
上面的代码表面上看好象可以完成任务,可上面的方法却是无效的。上面忽略了目录的深度与广度,在递归的过程中不断地分配资源(File[] files = file.listFiles();),而只有当更深层的递归结束时才能结束当前的工作并释放这些资源,这样极容易导致堆栈溢出和 JVM 停止工作。
为了解决这样的问题,应该尽量避免使用递归。不用递归也不分配大量资源的方法才是有效的方法。
下面是不用递归时查找硬盘中的 "java.exe" 的程序。分析这个过程的状态机请见:http://www.yi-dao.com/works/model/sample/findFiles.ydm 下载这个文档,使用“易道模型”打开,易道模型下载:http://www.sharebank.com.cn/soft/soft_view.php?id=11135
-------------------------------------------------------
public class Test{
public static void main(String[] args) {
File[] roots = File.listRoots();
String nameToFind = "java.exe";
for (int i = 0; i < roots.length; i++) {
File[] files = findFiles(roots[i], nameToFind);
for (int j = 0; j < files.length; j++) {
System.out.println(files[j].getAbsolutePath());
}
}
}
public static File[] findFiles(File dir, String nameToFind) {
Stack curPath = new Stack();
curPath.push(dir);
return findFiles(curPath, nameToFind);
}
public static final int FIND_SUB = 0; // 找子节点
public static final int FIND_SIB = 1; // 找同级节点
public static final int FIND_END = 2; // 结束
public static File[] findFiles(Stack curPath, String nameToFind) {
/** 只检测目录 */
class MyDirFilter
implements FileFilter {
public boolean accept(File pathname) {
return (pathname != null) && pathname.isDirectory();
}
}
/** 只检测文件名相同 */
class MyFileFilter
implements FileFilter {
String toFind;
MyFileFilter(String toFind) {
this.toFind = toFind;
}
public boolean accept(File pathname) {
return (pathname != null) && pathname.isFile()
&& toFind.equalsIgnoreCase(pathname.getName());
}
}
MyFileFilter fileFilter = new MyFileFilter(nameToFind);
MyDirFilter dirFilter = new MyDirFilter();
int state = FIND_SUB; // 开始
LinkedHashSet found = new LinkedHashSet();
while (state != FIND_END) {
File dir = (File) curPath.pop(); // 当前目录
// System.out.println(dir.getAbsolutePath());
if (state == FIND_SUB) { // 查找子节点
File[] subDirs = dir.listFiles(dirFilter);
if (subDirs == null || subDirs.length == 0) { // 没有子节点
curPath.push(dir);
state = FIND_SIB; // 下一次需要找同级节点
}
else {
curPath.push(dir);
curPath.push(subDirs[0]);
state = FIND_SUB;
}
}
else if (state == FIND_SIB) { // 查找同级节点
File[] files = dir.listFiles(fileFilter);
if (files != null) {
for (int i = 0; i < files.length; i++) {
found.add(files[i]);
}
}
if (curPath.isEmpty()) {
state = FIND_END; // 已经没有可以找的了,需要退出查找过程
}
else {
File parentDir = (File) curPath.peek();
File[] sibDirs = parentDir.listFiles(dirFilter);
for (int i = 0; i < sibDirs.length; i++) {
if (dir.equals(sibDirs[i])) { // 找到了当前的位置
if (i + 1 < sibDirs.length) { // 存在下一个同级节点
curPath.push(sibDirs[i + 1]);
state = FIND_SUB; // 需要查找子节点
}
else { // 这就是最后一个同级节点
state = FIND_SIB;
}
break;
}
}
}
}
}
return (File[]) found.toArray(new File[found.size()]);
}
}
上面的方法在整个文件目录的遍历过程中只使用了一个 LinkedHashSet 来记录当前的路径信息,并没有在向更深层次遍历时大量开销过多的资源,所以JVM是可以承受的。这样的方法才有效。
- 深层次树状结构遍历的改进 查找硬盘中的 “java.exe”
- 查找深层次的子节点
- 游标与树状结构的遍历
- 树状结构对象的获取及遍历
- 继承类的存储结构深层次理解
- 使用java的File类遍历文件夹,打印树状结构(递归实现)
- Java中列出目录的树状结构
- 改进的二分查找
- 顺序查找的改进
- 折半查找的改进
- java树状结构
- 在树状数组中遍历查找
- 遍历查找集合或者数组中的某个元素的值 java代码 详解 Android开发
- Hibernate基础之十一:树状结构遍历
- JAVA 多态-深层次理解
- 进程(WINAPI),遍历并查找树状的进程信息,实现控制系统进程
- 树状结构的设计
- 树状结构的实现
- 面试时最经常被问到的问题(Frenquently asked interview questions)之Microsoft and other companies篇
- 面试时最经常被问到的问题(Frenquently asked interview questions)之终结篇--提问面试官
- 如何进行招聘面试:10分钟面试招到核心员工![zz]
- ADO Data Types与数据库值对应
- 测试一下自己在面试中的成绩[zz]
- 深层次树状结构遍历的改进 查找硬盘中的 “java.exe”
- 用C#实现在客户区拖动窗体(转自MSDN)
- 牢骚话
- 新开张.
- 根据汉字声母,要在表中找相关记录,怎么实现?比如输入"zgyh",就能找到所有“中国银行”的记录。
- 关于ASP/asp.net的上传问题
- IEEE浮点数表示法
- Eclipse主要插件Lomboz介绍(1)_ Introduction
- 直接把结果输出到打印机