Java基礎(二十二) 遞迴
阿新 • • 發佈:2020-12-14
遞迴
概述
- 遞迴:指的是當前方法呼叫自己的現象。
- 遞迴的分類:
- 遞迴分為兩類:直接遞迴和間接遞迴
- 直接遞迴:成為方法自身呼叫自己的情況
- 間接遞迴:可以歸結為:方法A呼叫了方法B,方法B呼叫了方法C,方法C返回來又呼叫了方法A。
注意事項:
-
-
- 遞迴一定要有邊界條件(條件限定),保證遞迴能夠停止下來,否則會發生棧記憶體溢位。
- 在遞迴當中雖然有限定條件,但是遞迴的次數也不能太多,否則也會發生棧記憶體異常現象。
- 構造方法禁止遞迴。
-
使用遞迴實現累計求和
計算1~n之間的和
分析:1+2+3+...+n---->n + (n-1) + (n - 2) + ...+1的累加和,遞迴呼叫。
程式碼示例:
1 public static void main(String[] args) {
2 int sum = sum(10);
3 System.out.println(sum);
4 }
/*
定義一個方法,使用遞迴操作
1 + 2 + 3+ 4 +...+n
n+(n-1)+(n-2)+(n-3)+…+1
已知:
最大值:n
最小值:1
使用遞迴必須明確:
1.遞迴的結束條件
2.遞迴的目的:獲取下一個被加的數字(n-1)
*/
public static int sum(int n){
if(n == 1){
return 1;
}
//獲取下一個被加的數字
return n + sum(n-1);
//return n == 1 ? 1 : sum(n-1) + n; 使用三目運算子更方便
}
備註:使用遞迴當中,main方法呼叫sum方法,sum方法會一直呼叫sum方法,導致在記憶體當中出現了很多個sum方法(頻繁地建立方法、呼叫方法、銷燬方法)效率非常低下,最好的方式就是for迴圈。
遞迴求階乘
階乘:所有小於及等於該數的正整數的乘積。
n的階乘:n! = n * (n-1) * (n-2) * (n-3) * ... * 3 * 2 * 1
程式碼示例:
1 public static int producr(int n){
2
3 if( n == 1){
4 return 1;
5 }
6 return producr(n-1) * n;
7 }
使用遞迴列印多級目錄
程式碼示例:
1 public static void main(String[] args) { 2 // 找到Hello檔案的路徑 3 File file = new File("C:\\Users\\admin\\Desktop\\Hello"); 4 //呼叫getAllFiles() 5 getAllFiles(file); 6 } 7 8 /* 9 定義一個方法,引數傳遞File型別的目錄 10 方法中要對目錄進行遍歷 11 */ 12 public static void getAllFiles(File file) { 13 // 表明file此時是一個目錄 14 System.out.println(file); 15 //首先先獲取到它直接子目錄和直接子檔案 16 File[] files = file.listFiles(); 17 // 遍歷files目錄 18 if (files != null) { 19 for (File f : files) { 20 //判斷如果得到的f是一個目錄的,需要再次遍歷 21 if (f.isDirectory()) { 22 //表明f是一個目錄,則繼續遍歷這個目錄 23 //getAllFiles方法就是獲取所有的檔案,引數傳遞的剛好是目錄,所以直接呼叫 24 //getAllFiles目錄 25 System.out.println(f); 26 getAllFiles(f); 27 } else { 28 System.out.println(f); 29 } 30 } 31 } 32 }
綜合案例
檔案搜尋
搜尋:C:\Users\admin\Desktop\Hello目錄中的所有的.txt檔案
分析:
1.目錄搜尋,無法判斷有多少級目錄,所以使用遞迴,遍歷所有的目錄
2.遍歷目錄的時候,獲取的是所有的子檔案,通過檔案的名稱來進行診斷,判斷是否符合給定的條件.txt
程式碼實現:
1 public static void main(String[] args) {
2 //構建一個File物件得到C:\Users\admin\Desktop\Hello路徑
3 File file = new File("C:\\Users\\admin\\Desktop\\Hello");
4 getAllTxt(file);
5
6 }
7 /*
8 定義一個方法,遍歷所有的.txt檔案
9 方法中依然需要傳遞引數目錄
10 */
11 public static void getAllTxt(File dir){
12 File[] files = dir.listFiles();
13 //遍歷files
14 if(files != null){
15 for (File f : files) {
16 //判斷f是否是一個目錄
17 if(f.isDirectory()){
18 getAllTxt(f);
19 }else {
20 //先獲取檔案的名稱
21 //再次判斷名稱是否以.txt結尾
22 //鏈式程式設計
23 if(f.getName().toLowerCase().endsWith(".txt")){
24 System.out.println(f);
25 }
26 }
27 }
28 }
29 }
檔案過濾器優化
java.io.FileFilter是一個介面,是File的過濾器,該介面的物件可以傳遞給File類的ListFiles(FileFilter)作為引數,介面當中只有一個方法:
boolean accept(File pathname):測試pathname是否應該包含在當前的File目錄中,如果符合返回true
示例程式碼:
1 public static void main(String[] args) {
2 //構建一個File物件得到C:\Users\admin\Desktop\Hello路徑
3 File file = new File("C:\\Users\\admin\\Desktop\\Hello");
4 getAllTxt(file);
5 }
6 /*
7 定義一個方法,遍歷所有的.txt檔案
8 方法中依然需要傳引數目錄
9 */
10 public static void getAllTxt(File dir) {
11 //System.out.println(dir);
12 //File[] files = dir.listFiles();
13 File[] files = dir.listFiles(new FileFilterImpl());
14 //遍歷files
15 for (File f : files) {
16 // 判斷f是否是一個目錄
17 if (f.isDirectory()) {
18 getAllTxt(f);
19 } else {
20 // 先獲取檔案的名稱
21 System.out.println(f);
22 }
23 }
24 }
25 // 實現類中的程式碼
26 @Override
27 public boolean accept(File pathname) {
28 if (pathname.isDirectory()) {
29 return true;
30 }
31 return pathname.getName()
32 .toLowerCase()
33 .endsWith(".txt");
34 }
Lambda優化
示例程式碼:
1 //FilenameFilter介面
2 File[] files = dir.listFiles((d,name) -> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt"));
3 //FileFilter介面
4 File[] files = dir.listFiles(pathname ->pathname.getName().toLowerCase().endsWith(".txt") || pathname.isDirectory());