1. 程式人生 > 其它 >Java基礎-20(01)總結,遞迴,IO流

Java基礎-20(01)總結,遞迴,IO流

1:遞迴(理解)

(1)方法定義中呼叫方法本身的現象

舉例:老和尚給小和尚講故事,我們學程式設計

(2)遞迴的注意事項;

A:要有出口,否則就是死遞迴

B:次數不能過多,否則記憶體溢位

C:構造方法不能遞迴使用

package cn.itcast_01;
/*
 * 遞迴:方法定義中呼叫方法本身的現象
 * 
 * 方法的巢狀呼叫,這不是遞迴。
 * Math.max(Math.max(a,b),c);
 * 
 * public void show(int n) {
 *  if(n <= 0) {
 *  System.exit(0);
 *  }
 *  System.out.println(n);
 *  show(--n);
 * }
 * 
 * 注意事項:
 *  A:遞迴一定要有出口,否則就是死遞迴
 *  B:遞迴的次數不能太多,否則就記憶體溢位
 *  C:構造方法不能遞迴使用
 * 
 * 舉例:
 *  A:從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是:
 *  從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是:
 *  從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是:
 *  從前有座山,山裡有座廟,廟裡有個老和尚和小和尚,老和尚在給小和尚講故事,故事是:
 *  ...
 *  廟掛了,或者山崩了
 *  B:學程式設計  -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費
 *   學程式設計  -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費
 *  學程式設計  -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費
 *  學程式設計  -- 高薪就業 -- 掙錢 -- 娶媳婦 -- 生娃娃 -- 放羊 -- 掙學費
 *  ...
 *  娶不到媳婦或者生不了娃娃 
 */
public class DiGuiDemo {
 // public DiGuiDemo() {
 // DiGuiDemo();
 // }
}

(3)遞迴的案例:

A:遞迴求階乘

package cn.itcast_02;
/*
 * 需求:請用程式碼實現求5的階乘。
 * 下面的知識要知道:
 *  5! = 1*2*3*4*5
 *  5! = 5*4!
 * 
 * 有幾種方案實現呢?
 *  A:迴圈實現
 *  B:遞迴實現
 *  a:做遞迴要寫一個方法
 *  b:出口條件
 *  c:規律
 */
public class DiGuiDemo {
 public static void main(String[] args) {
 int jc = 1;
 for (int x = 2; x <= 5; x++) {
 jc *= x;
 }
 System.out.println("5的階乘是:" + jc);
 System.out.println("5的階乘是:"+jieCheng(5));
 }
 /*
  * 做遞迴要寫一個方法:
  *  返回值型別:int
  *  引數列表:int n
  * 出口條件:
  *  if(n == 1) {return 1;}
  * 規律:
  *  if(n != 1) {return n*方法名(n-1);}
  */
 public static int jieCheng(int n){
 if(n==1){
 return 1;
 }else {
 return n*jieCheng(n-1);
 }
 }
}

B:兔子發展問題 (斐波那契數列)

package cn.itcast_02;
/*
 * 有一對兔子,從出生後第3個月起每個月都生一對兔子,小兔子長到第三個月後每個月又生一對兔子,假如兔子都不死,問第二十個月的兔子對數為多少?
 * 分析:我們要想辦法找規律
 *  兔子對數
 * 第一個月:  1
 * 第二個月: 1
 * 第三個月: 2
 * 第四個月: 3 
 * 第五個月: 5
 * 第六個月: 8
 * ...
 * 
 * 由此可見兔子物件的資料是:
 *  1,1,2,3,5,8...
 * 規則:
 *  A:從第三項開始,每一項是前兩項之和
 *  B:而且說明前兩項是已知的
 * 
 * 如何實現這個程式呢?
 *  A:陣列實現
 *  B:變數的變化實現
 *  C:遞迴實現
 * 
 * 假如相鄰的兩個月的兔子對數是a,b
 * 第一個相鄰的資料:a=1,b=1
 * 第二個相鄰的資料:a=1,b=2
 * 第三個相鄰的資料:a=2,b=3
 * 第四個相鄰的資料:a=3,b=5
 * 看到了:下一次的a是以前的b,下一次是以前的a+b 
 */
public class DiGuiDemo2 {
 public static void main(String[] args) {
 // 定義一個數組
 int[] arr = new int[20];
 arr[0] = 1;
 arr[1] = 1;
 // arr[2] = arr[0] + arr[1];
 // arr[3] = arr[1] + arr[2];
 // ...
 for (int x = 2; x < arr.length; x++) {
 arr[x] = arr[x - 2] + arr[x - 1];
 }
 System.out.println(arr[19]);// 6765
 System.out.println("----------------");
 int a = 1;
 int b = 1;
 for (int x = 0; x < 18; x++) {
 // 臨時變數儲存上一次的a
 int temp = a;
 a = b;
 b = temp + b;
 }
 System.out.println(b);
 System.out.println("----------------");
 System.out.println(fib(20));
 }
 /*
  * 方法: 返回值型別:int 引數列表:int n 出口條件: 第一個月是1,第二個月是1 規律: 從第三個月開始,每一個月是前兩個月之和
  */
 public static int fib(int n) {
 if (n == 1 || n == 2) {
 return 1;
 } else {
 return fib(n - 1) + fib(n - 2);
 }
 }
}

C:遞迴輸出指定目錄下所有指定字尾名的檔案絕對路徑

package cn.itcast_03;
import java.io.File;
/*
 * 需求:請大家把E:JavaSE目錄下所有的java結尾的檔案的絕對路徑給輸出在控制檯。
 * 
 * 分析:
 *  A:封裝目錄
 *  B:獲取該目錄下所有的檔案或者資料夾的File陣列
 *  C:遍歷該File陣列,得到每一個File物件
 *  D:判斷該File物件是否是資料夾
 *  是:回到B
 *  否:繼續判斷是否以.java結尾
 *  是:就輸出該檔案的絕對路徑
 *  否:不搭理它
 */
public class FilePathDemo {
 public static void main(String[] args) {
 // 封裝目錄
 File srcFolder = new File("E:\JavaSE");
 // 遞迴功能實現
 getAllJavaFilePaths(srcFolder);
 }
 private static void getAllJavaFilePaths(File srcFolder) {
 // 獲取該目錄下所有的檔案或者資料夾的File陣列
 File[] fileArray = srcFolder.listFiles();
 // 遍歷該File陣列,得到每一個File物件
 for (File file : fileArray) {
 // 判斷該File物件是否是資料夾
 if (file.isDirectory()) {
 getAllJavaFilePaths(file);
 } else {
 // 繼續判斷是否以.java結尾
 if (file.getName().endsWith(".java")) {
 // 就輸出該檔案的絕對路徑
 System.out.println(file.getAbsolutePath());
 }
 }
 }
 }
}

D:遞迴刪除帶內容的目錄(小心使用)

package cn.itcast_03;
import java.io.File;
/*
 * 需求:遞迴刪除帶內容的目錄
 * 
 * 目錄我已經給定:demo
 * 
 * 分析:
 *  A:封裝目錄
 *  B:獲取該目錄下的所有檔案或者資料夾的File陣列
 *  C:遍歷該File陣列,得到每一個File物件
 *  D:判斷該File物件是否是資料夾
 *  是:回到B
 *  否:就刪除
 */
public class FileDeleteDemo {
 public static void main(String[] args) {
 // 封裝目錄
 File srcFolder = new File("demo");
 // 遞迴實現
 deleteFolder(srcFolder);
 }
 private static void deleteFolder(File srcFolder) {
 // 獲取該目錄下的所有檔案或者資料夾的File陣列
 File[] fileArray = srcFolder.listFiles();
 if (fileArray != null) {
 // 遍歷該File陣列,得到每一個File物件
 for (File file : fileArray) {
 // 判斷該File物件是否是資料夾
 if (file.isDirectory()) {
 deleteFolder(file);
 } else {
 System.out.println(file.getName() + "---" + file.delete());
 }
 }
 System.out
 .println(srcFolder.getName() + "---" + srcFolder.delete());
 }
 }
}

2:IO流(掌握)

(1)IO用於在裝置間進行資料傳輸的操作

(2)分類:

A:流向

輸入流 讀取資料

輸出流 寫出資料

B:資料型別

位元組流

位元組輸入流

位元組輸出流

字元流

字元輸入流

字元輸出流

注意:

a:如果我們沒有明確說明按照什麼分,預設按照資料型別分。

b:除非檔案用windows自帶的記事本開啟我們能夠讀懂,才採用字元流,否則建議使用位元組流。

(3)FileOutputStream寫出資料

A:操作步驟

a:建立位元組輸出流物件

b:呼叫write()方法

c:釋放資源

B:程式碼體現:

 FileOutputStream fos = new FileOutputStream("fos.txt");
 fos.write("hello".getBytes());
 fos.close(); 

C:要注意的問題?

a:建立位元組輸出流物件做了幾件事情?

b:為什麼要close()?

package cn.itcast_01;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
 * IO流的分類:
 *  流向:
 *  輸入流 讀取資料
 *  輸出流 寫出資料
 *  資料型別:
 *  位元組流
 *  位元組輸入流 讀取資料 InputStream
 *  位元組輸出流 寫出資料 OutputStream
 *  字元流
 *  字元輸入流 讀取資料 Reader
 *  字元輸出流 寫出資料 Writer
 * 
 *  注意:一般我們在探討IO流的時候,如果沒有明確說明按哪種分類來說,預設情況下是按照資料型別來分的。
 * 
 * 需求:我要往一個文字檔案中輸入一句話:"hello,io"
 * 
 * 分析:
 *  A:這個操作最好是採用字元流來做,但是呢,字元流是在位元組流之後才出現的,所以,今天我先講解位元組流如何操作。
 *  B:由於我是要往檔案中寫一句話,所以我們要採用位元組輸出流。
 * 
 * 通過上面的分析後我們知道要使用:OutputStream
 * 但是通過檢視API,我們發現該流物件是一個抽象類,不能例項化。
 * 所以,我們要找一個具體的子類。
 * 而我們要找的子類是什麼名字的呢?這個時候,很簡單,我們回想一下,我們是不是要往檔案中寫東西。
 * 檔案是哪個單詞:File
 * 然後用的是位元組輸出流,聯起來就是:FileOutputStream
 * 注意:每種基類的子類都是以父類名作為字尾名。
 *  XxxOutputStream
 *  XxxInputStream
 *  XxxReader
 *  XxxWriter
 * 檢視FileOutputStream的構造方法:
 *  FileOutputStream(File file) 
 * FileOutputStream(String name)
 *
 * 位元組輸出流操作步驟:
 *  A:建立位元組輸出流物件
 *  B:寫資料
 *  C:釋放資源
 */
public class FileOutputStreamDemo {
 public static void main(String[] args) throws IOException {
 // 建立位元組輸出流物件
 // FileOutputStream(File file)
 // File file = new File("fos.txt");
 // FileOutputStream fos = new FileOutputStream(file);
 // FileOutputStream(String name)
 FileOutputStream fos = new FileOutputStream("fos.txt");
 /*
  * 建立位元組輸出流物件了做了幾件事情:
  * A:呼叫系統功能去建立檔案
  * B:建立fos物件
  * C:把fos物件指向這個檔案
  */
 //寫資料
 fos.write("hello,IO".getBytes());
 fos.write("java".getBytes());
 //釋放資源
 //關閉此檔案輸出流並釋放與此流有關的所有系統資源。
 fos.close();
 /*
  * 為什麼一定要close()呢?
  * A:讓流物件變成垃圾,這樣就可以被垃圾回收器回收了
  * B:通知系統去釋放跟該檔案相關的資源
  */
 //java.io.IOException: Stream Closed
 //fos.write("java".getBytes());
 }
}

c:如何實現資料的換行?

d:如何實現資料的追加寫入?

package cn.itcast_01;
import java.io.FileOutputStream;
import java.io.IOException;
/*
 * 如何實現資料的換行?
 *  為什麼現在沒有換行呢?因為你值寫了位元組資料,並沒有寫入換行符號。
 *  如何實現呢?寫入換行符號即可唄。
 *  剛才我們看到了有寫文字檔案開啟是可以的,通過windows自帶的那個不行,為什麼呢?
 *  因為不同的系統針對不同的換行符號識別是不一樣的?
 *  windows:rn
 *  linux:n
 *  Mac:r
 *  而一些常見的個高階記事本,是可以識別任意換行符號的。
 * 
 * 如何實現資料的追加寫入?
 *  用構造方法帶第二個引數是true的情況即可
 */
public class FileOutputStreamDemo3 {
 public static void main(String[] args) throws IOException {
 // 建立位元組輸出流物件
 // FileOutputStream fos = new FileOutputStream("fos3.txt");
 // 建立一個向具有指定 name 的檔案中寫入資料的輸出檔案流。如果第二個引數為 true,則將位元組寫入檔案末尾處,而不是寫入檔案開始處。
 FileOutputStream fos = new FileOutputStream("fos3.txt", true);
 // 寫資料
 for (int x = 0; x < 10; x++) {
 fos.write(("hello" + x).getBytes());
 fos.write("rn".getBytes());
 }
 // 釋放資源
 fos.close();
 }
}

e:異常處理的位元組輸出流操作

package cn.itcast_01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
 * 加入異常處理的位元組輸出流操作
 */
public class FileOutputStreamDemo4 {
 public static void main(String[] args) {
 // 分開做異常處理
 // FileOutputStream fos = null;
 // try {
 // fos = new FileOutputStream("fos4.txt");
 // } catch (FileNotFoundException e) {
 // e.printStackTrace();
 // }
 //
 // try {
 // fos.write("java".getBytes());
 // } catch (IOException e) {
 // e.printStackTrace();
 // }
 //
 // try {
 // fos.close();
 // } catch (IOException e) {
 // e.printStackTrace();
 // }
 // 一起做異常處理
 // try {
 // FileOutputStream fos = new FileOutputStream("fos4.txt");
 // fos.write("java".getBytes());
 // fos.close();
 // } catch (FileNotFoundException e) {
 // e.printStackTrace();
 // } catch (IOException e) {
 // e.printStackTrace();
 // }
 // 改進版
 // 為了在finally裡面能夠看到該物件就必須定義到外面,為了訪問不出問題,還必須給初始化值
 FileOutputStream fos = null;
 try {
 // fos = new FileOutputStream("z:\fos4.txt");
 fos = new FileOutputStream("fos4.txt");
 fos.write("java".getBytes());
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 // 如果fos不是null,才需要close()
 if (fos != null) {
 // 為了保證close()一定會執行,就放到這裡了
 try {
 fos.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 }
 }
}