在测试类中,有一个静态方法返回特定目录中的一组所有文件。
因为该方法调用自身来循环文件,所以我在该方法之外实例化了一组listOfFiles
,以添加我找到的文件。第一次调用该方法时效果很好,但第二次调用时,listOfFiles
被累加起来,由于return语句,我无法清除它。有什么想法吗?
import java.io.File;
import java.util.HashSet;
class TestClass {
static HashSet<File> listOfFiles = new HashSet<File>();
//returns all files in the directory as a set
static HashSet<File> getAllFiles(File file) {
if(file.isDirectory()) {
for(File subFiles : file.listFiles()) {
if(subFiles.isDirectory()) {
getAllFiles(subFiles);
} else {
listOfFiles.add(subFiles);
}
}
} else {
listOfFiles.add(file);
}
// listOfFiles.clear();
return listOfFiles;
}
}
public class Test {
public static void main(String[] args) {
TestClass.getAllFiles(new File("C:\\Users\\user\\Documents")).forEach(System.out::println);
TestClass.getAllFiles(new File("C:\\Users\\user\\Desktop")).forEach(System.out::println);
}
}
如果我编写更多的方法,或者每次调用该方法时手动清除集合,我可能会解决这个问题,但这一切似乎都不优雅和干净。
static HashSet<File> getAllFiles(File file) {
HashSet<File> set = new HashSet<>();
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
set.addAll(getAllFiles(f));
} else {
set.add(f);
}
}
}
return set;
}
我觉得这里有点混乱。对于递归方法,您使用的是混合方法。
您应该依赖一个只使用静态
字段且没有返回语句(不推荐)的实现,或者依赖一个返回包含遇到的文件的局部变量的实现。
在第一个场景中,您不需要返回语句,因为每个方法调用总是在同一个HashSet
实例上工作。静态关键字用于将成员从实例成员“转换”为类成员。具体来说,当一个字段被声明为静态时,无论创建了多少个该类的实例,都会创建该字段的单个实例。总会有一个静态字段的单个实例,其值将在每个静态和非静态上下文中共享。因此,当您在第一次主调用中更新listOfFiles
的内容时,第二次调用仍然会看到第一次调用的结果,因为它们都在同一个HashSet
实例上工作。
在这个实现中,您应该始终记住在每次调用getAllFiles
之前清除HashSet
,这绝对不是最干净也不是最好的方法。getAllFiles方法应该是独立的,并返回只属于其计算的内容。静态解决方案应该如下所示:
public class TestClass {
static HashSet<File> listOfFiles = new HashSet<File>();
static void getAllFiles(File file) {
if (file.isDirectory()) {
for (File subFiles : file.listFiles()) {
if (subFiles.isDirectory()) {
getAllFiles(subFiles);
} else {
listOfFiles.add(subFiles);
}
}
} else {
listOfFiles.add(file);
}
}
public static void main(String[] args) {
//The first call does not need to clear the HashSet since it is empty at the beginning
getAllFiles(new File("C:\\Users\\user\\Documents"));
TestClass.listOfFiles.forEach(System.out::println);
System.out.println();
//The second call needs to clear the results from the previous invocation
listOfFiles.clear();
getAllFiles(new File("C:\\Users\\user\\Desktop"));
TestClass.listOfFiles.forEach(System.out::println);
}
}
我推荐的第二种方法是使用本地HashSet实例,该实例将被返回并添加到调用方的HashSet中。
public class TestClass {
static HashSet<File> listOfFiles = new HashSet<File>();
static HashSet<File> getAllFiles(File file) {
HashSet<File> localListOfFiles = new HashSet<File>();
if (file.isDirectory()) {
for (File subFiles : file.listFiles()) {
if (subFiles.isDirectory()) {
//Adding to the local HashSet the HashSet returned from my inner call
localListOfFiles.addAll(getAllFiles(subFiles));
} else {
localListOfFiles.add(subFiles);
}
}
} else {
localListOfFiles.add(file);
}
return localListOfFiles;
}
public static void main(String[] args) {
TestClass.getAllFiles(new File("C:\\Users\\user\\Documents")).forEach(System.out::println);
TestClass.getAllFiles(new File("C:\\Users\\user\\Desktop")).forEach(System.out::println);
}
}
不要使用静态
字段。
而是在第一次调用时创建一个HashSet
,并将其传递给所有其他调用。
最简单的方法是使用一个单独的助手方法,如下所示:
public static Set<File> getAllFiles(File file) {
Set<File> result = new HashSet<>();
getAllFilesImpl(file, result);
return result;
}
private static void getAllFilesImpl(File file, Set<File> result) {
if(file.isDirectory()) {
for(File subFile : file.listFiles()) {
if(subFile.isDirectory()) {
getAllFilesImpl(subFile, result);
} else {
result.add(subFile);
}
}
} else {
result.add(file);
}
}
注意,我还将getAllFiles()
的返回类型更改为仅Set
假设我有一些这样的方法: 但我不想调用序列方法: 这很无聊。如果我添加一个新方法:,我需要添加手动:
我正在寻找一些帮助来优化我的代码并使用更少的行数编写它。我有一个Class say A,它有几个定义的方法,如下所示: 现在我有一个单独的类,比如B和方法,编写如下 所有这些代码都运行良好。我只是想看看是否有更好的方法可以继续调用像objA这样的方法。verifyMyMethods()中的doSomethingA(),因此我可以使用更少的代码行来完成相同的工作。 我想在循环中调用方法doSomet
我有一个类(称为name),它有如下不同的方法: alex(), john(), claire(), charles(), luke(), richard(), jen()等等 我需要逐一调用所有这些方法,例如: ... 等等 我尝试的是创建一个名称列表,并调用循环中的所有方法 但这种调用方法的方式正在失败。有没有办法在循环中调用同一类的多个方法?
问题内容: 我正在编写一个游戏引擎,其中使用for循环迭代保存在a 中的一组对象。显然,效率非常重要,因此我想知道循环的效率。 当返回的秒。我想知道的是,每次循环在新扩展上进行迭代时,是否都调用该方法。如果是这样,这样做会更有效: ?提前致谢。 问题答案: 按照规范,这个成语 扩展成 因此,您询问的呼叫在循环初始化时仅发生一次。这是迭代器对象,其方法被重复调用。 但是,如果您真的对应用程序的性能感
本文向大家介绍C#中for循环、while循环循环执行的方法,包括了C#中for循环、while循环循环执行的方法的使用技巧和注意事项,需要的朋友参考一下 先给大家介绍下C#中的循环执行for循环 在这一节练习中,我们向大家介绍一下C#中的另一种重要的循环语句,for循环。 表达式1:一般为赋值表达式,给控制变量赋初值; 表达式2:逻辑表达式,循环控制条件;当条件为真时,循环执行循环体中的语句。
主要内容:优点,缺点轮循调度算法是最流行的调度算法之一,它可以在大多数操作系统中实际实现。 这是先到先得的排程先发制人的版本。 该算法着重于时间共享。 在这个算法中,每个进程都以循环方式执行。 在称为时间量的系统中定义了一定的时间片。 就绪队列中的每个进程都分配给该时间段的CPU,如果在该时间内进程的执行完成,那么进程将终止,否则进程将返回就绪队列并等待下一轮完成 执行。 优点 它可以在系统中实际实现,因为它不依赖于