Requirement: scan all subfolders of D:\test and. jpg files under the subfolders.
If we use a loop to do this, we don't know the end condition of the loop or how many layers there are, so it's more troublesome.
We can use a new idea: recursion.
Examples of recursion:
Once upon a time, there was a mountain with a temple. There was an old monk in the temple. The old monk was telling a story to the little monk:
Once upon a time, there was a mountain with a temple. There was an old monk in the temple. The old monk was telling a story to the little monk:
Once upon a time, there was a mountain with a temple. There was an old monk in the temple. The old monk was telling a story to the little monk:
. . . . . . .
How can the story end: the little monk returned to secular life. The temple collapsed. Landslide.
Recursion in Java:
The method itself is called in the function body of the method.
Details of recursive call: it must be required that there is an end condition for function call in recursion. Otherwise, the function will be called all the time, which will lead to memory overflow.
Recursive demonstration
Exercise 1: Requirements: calculate the sum of 1 ~ 5. Do not use cycles.
Analysis and steps:
1) Define a DiGuiDemo test class;
2) call the custom function in the main function of this class, 5 as the parameter of the function, use a variable sum to receive the returned value and output the sum value sum;
3) The user-defined add() function receives the passed parameter 5;
4) Write an if statement in the user-defined function to judge whether I is greater than 1. if it is greater than 1, use return to return i+add(i-1);
5) Otherwise, when I < = 1, return 1;
Author: Villain, Cc
Link: https://www.jianshu.com/p/73ae186721db
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.
package cn.xuexi.digui.demo; /* * Exercise 1: Requirements: calculate the sum of 1 ~ 5. Do not use cycles. * Recursive demonstration */ public class DiGuiDemo { public static void main(String[] args) { //Call the user-defined function to find the sum value between 1 and 5 int sum=add(5); System.out.println(sum); } /* * The user-defined function calculates the sum value between 1 and 5 * 5+4+3+2+1 */ public static int add(int n) { /* * Determine whether n is greater than 1 */ if(n>1) { //The add function here calls the function itself, which is called recursively return n+add(n-1); } //Returns 1 as the end condition of recursion return 1; } }
The above code diagram is shown in the figure below:
Exercise 2: demand: find the factorial of 5!!
analysis:
Popularize the knowledge of Mathematics:
Mode 1:5= 5 * 4 * 3 * 2 * 1 = 120;
Mode 1 cycle mode:
The code is as follows:
Steps:
1) Define a DiGuiDemo2 test class;
2) call the user-defined function jc() in the main function in this class, 5 as the parameter of the function, use a variable result to receive the value of the returned factorial, and output the result result;
3) The user-defined jc() function receives the passed parameter 5;
4) Define a variable result=1 in the user-defined function, use the for loop to realize the factorial result of method 1, and return the value of result factorial;
package cn.xuexi.digui.demo; /* * Exercise 2: demand: find the factorial of 5!! * Mode 1:5= 5*4*3*2*1=120 */ public class DiGuiDemo2 { public static void main(String[] args) { int result=jc(5); //Output factorial results System.out.println(result);//120 } //Use method 1 to find the factorial of 5 public static int jc(int n) { //Define a variable to receive the factorial result int result =1; for (int i = 2; i <= n; i++) { result=result*i; } return result; } }
Method 2: use recursive thought to complete
5! = 5 * 4! 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1*0!
Find rules: n= n * (n-1)!
Supplement: 0! Equal to 1
End condition: if (n < = 1) return 1;
Mode 2 recursive mode:
The code is as follows:
Steps:
1) Define a DiGuiDemo3 test class;
2) call the user-defined function jc2() in the main function in this class, 5 as the parameter of the function, use a variable result to receive the value of the returned factorial, and output the result result;
3) The user-defined jc2() function receives the passed parameter 5;
4) Write an if statement in a user-defined function to determine whether n is less than or equal to 1. if n is less than or equal to 1, use return to return 1;
5) Otherwise, if n > 1, use return to return n * jc2(n - 1);
package cn.xuexi.digui.demo; /* * Method 2: use the recursive idea to solve the factorial of 5 *Method 1: 5= 5*4*3*2*1; *Mode 2: 5= 5*4! * 4!=4*3! * 3!=3*2! * 2!=2*1! * 1!=1*0! *Find rules: n= n*(n-1)! *Find end condition: * if(n<=1) return 1; */ public class DiGuiDemo3 { public static void main(String[] args) { // Call the function to find the factorial of 5 int result=jc2(5); System.out.println(result);//120 } //Factorization of 5 by user-defined function public static int jc2(int n) { // End condition if(n<=1) { return 1; } return n*jc2(n-1); } }
The above code memory diagram is as follows:
Recursive considerations
1) Recursion must have an end condition, otherwise the stack memory will overflow, which is called dead recursion! The stack blew up.
The exception of stack memory overflow message is as follows:
2) The number of recursions cannot be too many, otherwise the stack overflows. It blew up
The exception of stack memory overflow message is as follows:
3) The constructor cannot be recursive, memory overflows, and an error is reported directly during compilation
Summary: recursive containers can easily lead to memory overflow. Even if there is an end condition in the recursive call, memory overflow will occur if the number of recursions is too many.
Therefore, we should be careful when using recursive calls of functions in development.
Recursive exercise
The Fibonacci sequence is either called the golden section sequence or the rabbit sequence:
Immortal rabbit question: there is a pair of rabbits. From the third month of birth, a pair of rabbits are born every month. If the rabbits do not die, how many pairs of rabbits are there in the nth month.
The illustration of Fibonacci's thought of sequence is shown in the figure below:
The thought of Fibonacci sequence is as follows:
Law finding:
Month (n): 1 2 3 4 5 6 7 8 9 10
Rabbit logarithm (f): 1 1 2 3 5 8 13 21 34 55
f(n) = f(n-1) + f(n-2)
Find exit:
if(n <= 2) return 1;
The code implementation is as follows:
Analysis and steps:
1) Define a test class DiguiDemo4;
2) call the user-defined function countRabbits() in the DiguiDemo4 class, specifying the month as the parameter, just to see how many rabbits there are in the next few months, using an integer variable to receive the logarithmic num of the rabbit returned, and print out the result.
3) The user-defined function countrabbit() outputs the logarithm of rabbits in the corresponding month according to the month specified by the user;
4) Use the judgment structure to judge whether the month n is less than or equal to 2. If yes, return 1 pair;
5) If the month is greater than 2, recursively call the function countrabbit (n-1) + countrabbit (n-2) respectively, and return the logarithm of the rabbit to the caller;
package cn.xuexi.digui.demo; /* * Recursive practice, Fibonacci sequence * Month: 1 2 3 4 5 6 7 8 9 10... * Number of rabbits: 1 1 2 3 5 8 13 21 34 55... * Find the logarithm of rabbits in the nth month */ public class DiGuiDemo4 { public static void main(String[] args) { // Define a function to calculate the logarithm of the rabbit int num=countRabbits(6);//6 means month //Output the logarithm of rabbits in the nth month System.out.println(num); } //The user-defined function counts the logarithm of rabbits in the nth month public static int countRabbits(int n) //n means month { // End condition if(n<=2) { return 1; } //law return countRabbits(n-1)+countRabbits(n-2); } }
Comprehensive exercise
Exercise 1: scan all subfolders of D:\test and. jpg files under the subfolders, and output their absolute paths
Requirements: scan all subfolders of D:\test and. jpg files under subfolders, and output their absolute paths.
analysis:
First, we can get all the sons under D:\test. We judge whether the son is a folder. If so, scan the son's folder again, and then obtain all the sub files and sub folders under the son, that is, the grandson of D:\test. Then we judge whether the grandson is a folder, and so on. Finally, we output its absolute path;
Idea:
A: Encapsulate the File object of the parent directory;
B: Get the File array of all sons in the parent directory;
C: Loop traversal to obtain each son;
D: Determine whether it is a folder
Yes: go back to step B and continue to get grandchildren
No: judge whether it is a condition for. jpg to end recursion
Yes: Print
No: regardless
We find that the process from B to D is repeated. We can encapsulate it into recursive functions.
Steps:
1) Create test class FileTest1;
2) Encapsulate the object parent of the parent directory D:\test in the main function of FileTest1 class;
3) Call the function scanFolders(parent) of recursive scanning;
4) The user-defined function scanFolders() uses the parent directory object to call the listFiles() function to obtain the File array files of all sons in the parent directory;
5) Loop traversal to obtain each son object file;
6) Use the file object to call the isDirectory() function to determine whether it is a folder;
7) If it is a folder, call the scanFolders(file) function recursively;
8) If it is not a folder, it must be a file. Use the file object to call the getName() function to obtain the full name of the file, and call the endsWith() function to determine whether the suffix is. jpg. If it is the absolute path to which the output file belongs;
package cn.xuexi.file.test; import java.io.File; /* * Requirements: scan D:\test all sub files and. jpg files under sub files, and output their absolute paths. * Idea: * A:Create parent directory * B:Call the function to find a file or folder * C:Get the File array of all sons by calling the function from the parent directory object * D:Loop through all the sons. dir represents each son of the parent directory D:\test * a:Determine whether the obtained dir is a folder. If yes, proceed to step B * b:No, judge whether the suffix is. jpg. Yes, output the absolute path * * We find that the process from B to D is repeated. We can encapsulate it into recursive functions. */ public class FileTest1 { public static void main(String[] args) { //Encapsulates the object of the parent directory File parent = new File("D:\\test"); //Call the function to find a file or folder scanFolderAndFile(parent); } //Custom functions scan files or folders public static void scanFolderAndFile(File parent) { //Get the File array of all sons by calling the function from the parent directory object File[] dirs = parent.listFiles(); //Loop through all the sons. dir represents each son of the parent directory D:\test for (File dir : dirs) { /* * Determine whether the obtained dir is a folder * If it is a folder, continue to scan or find all the files or folders under your son * and so on * If it is not a folder, it must be a file. Judge whether the suffix is. jpg * If it is. jpg, its absolute path is output */ if(dir.isDirectory()) { //Continue to find the following files or folders to perform the scan function scanFolderAndFile(dir); }else { /* * The description is not a folder, but a file. We judge whether it is. jpg * dir.getName()Indicates the name of the obtained file mm.jpg */ if(dir.getName().endsWith(".jpg")) { //The suffix of the description file is. jpg, and its absolute path is output System.out.println(dir.getAbsolutePath()); } } } } }
Code with robustness:
The above code is unsafe,
1) For example, when calling the scanFolders(parent) function, if the parent becomes null, when scanFolders(File parent) receives parameters, the parent is also null, and a null pointer exception will be reported;
Judge whether the parent is null. If it is null, throw an exception;
2) For example, when creating a parent directory object, if the specified parent directory does not exist in the computer, throw an exception;
Use the parent object to call the exit() function to judge whether the created folder exists. If it does not exist, throw an exception.
3) For example, when creating a parent directory object, if the specified parent directory is a file, an exception is thrown;
Use the parent object to call the isFile() function. If it is a file, throw an exception.
Note: except for the above three problems, other codes are the same as the above codes.
The code is as follows:
Custom function scan folder public static void scanFolderAndFile(File parent) { //Determine whether the parent is null if(parent==null) { throw new RuntimeException("Cannot pass null"); } //Determine whether the folder exists if(!parent.exists()) { throw new RuntimeException("Folder does not exist"); } //The passed is a folder, not a file if(parent.isFile()) { throw new RuntimeException("It can only be a folder"); } // Get all the children under the parent directory File[] files = parent.listFiles(); //Traverse the above array for (File file : files) { /* * If a folder is encapsulated in the file object, the folder can be regarded as a parent class * Scanning his son below */ if(file.isDirectory()) { //The description is that the folder is returned to the scanFolderAndFile() function again to execute the function scanFolderAndFile(file); }else { /* * Description file encapsulates a file * Get the file name and determine whether the suffix is. jpg * If yes, get the absolute path */ boolean boo = file.getName().endsWith(".jpg"); if(boo) { //Description the absolute path of the file output with the suffix. jpg System.out.println(file.getAbsolutePath()); } } } }
Exercise 2: implement the exercise using filters
Demo: Requirements: scan all subfolders of D:\test and. jpg files under subfolders, and output their absolute paths.
Requirement: implemented using filters.
Idea:
A: Create the File object of the parent directory
B: Get the qualified son under the parent directory
What are the conditions?
It can be a folder or a. jpg file
C: Loop through and take out each son
There are two situations for the extracted son: folder and. jpg file
D: Determine whether it is a folder
Yes: back to B
No: print
B to D are encapsulated into recursive functions
Steps:
1) Create test class FileTest2;
2) Encapsulate the object parent of the parent directory D:\test in the main function of FileTest2 class;
3) Call the function scanFolders(parent) of recursive scanning;
4) The user-defined function scanFolders() uses the parent directory object to call the listFiles(new FileFilter()) function to obtain the File array files of all sons under the parent directory;
5) The anonymous inner class of the FileFilter interface is used as the parameter of the listFiles() function, and the anonymous inner class implements the accept function;
6. In the accept function body, use the child object of the parent directory to call isDirectory() function and getName().endsWith(".jpg") function to judge whether the child of the parent directory is a folder or a file with a. jpg suffix;
7) Use the judgment structure to judge whether there are files or folders in the files array;
8) If so, loop through the array files;
9) Use the file object to call the isDirectory() function to determine whether it is a folder;
10) If it is a folder, call the scanFolders(file) function recursively;
11) If it is not a folder, it must be a file. Use the file object to call the getName() function to obtain the full name of the file, and call the endsWith() function to determine whether the suffix is. jpg. If it is the absolute path to which the output file belongs;
package cn.xuexi.file.test; import java.io.File; import java.io.FileFilter; /* * Idea: A: Create the File object of the parent directory B: Get the qualified son under the parent directory What are the conditions? It can be a folder or a. jpg file C: Loop through and take out each son There are two situations for the extracted son: folder and. jpg file D: Determine whether it is a folder Yes: back to B No: print B To D encapsulated into recursive functions */ public class FileTest3 { public static void main(String[] args) { // Encapsulates the object of the parent directory File parent = new File("D:\\test"); // Call the function to find a file or folder scanFolderAndFile(parent); } public static void scanFolderAndFile(File parent) { // Get the qualified sons under the parent directory. You need to use a filter here File[] files=parent.listFiles(new FileFilter() { public boolean accept(File pathname) { // The condition is a folder or a file with the suffix. jpg return pathname.isDirectory() || pathname.getName().endsWith(".jpg"); } }); //Loop through and take out each son for (File file : files) { // Determine whether it is a folder if(file.isDirectory()) { //Recursive call function scanFolderAndFile(file); }else { System.out.println(file.getAbsolutePath()); } } } }
Pay attention to my 5 K!! Share more dry goods!!!!