Java筆記(1)泛型、集合與檔案操作

約 7 分鐘

泛型(Generics)

  • 泛型是多型(polymorphism)的一種技巧
  • 當編譯期間無法確定程式碼的撰寫方式,而是依照執行期間的狀況而決定
  • 不用因為資料型別的限制而實作多種方法,只需要一種方法即可
  • 定義「安全的」泛型類別(Genericsclass),泛型提供編譯時期檢查

泛型用<參數(自定義)>表示,也可以像一般變數一樣傳進多個參數進去,

泛型通常最常使用的情況是,當不確定使用的參數的時候,不用因為資料型別的限制而實作許多方法。

public class Foo<T>{
  private T f;
}
public class Foo<T1,T2>{
  private T1 fl;
  private T2 f2; 
}

通配字元(Wildcard)

  • 共變性
  • 繼承於List的子類別或實作List介面的類別
  • List的父類別
  • 通配字元(?)不能當作宣告方法的型別,必須是變數名稱

使用方式比泛型<>多了一個?

使用範例:

Doo<? extends List >  // 代表?的類別必須是繼承於List的子型別或是實作List介面的類別
Doo<? super List >    //必須是List的父類別
Foo<? extends List> fooObj = new Foo<ArrrayList>(); //因為ArrayList是List子型別,才可以這樣使用。
 
Foo<? super ArrayList> fooObj = new Foo<List>(); //代表要是Array的父類別才可以使用

ArrayList

集合(COLLECTIONS)

  • 將許多同⼀種資料型態的物件集合在⼀起
  • 比陣列更有彈性好處理

List(有序集合)

  • 將物件依序存放,並依序取出
  • 可以存放重複的物件

官方API文件:https://docs.oracle.com/javase/8/docs/api/java/util/List.html

可以看到了副類別是Collection,且用了泛型Interface List<E>

常用方法:

返回值 說明
boolean add(E e)將指定元素加到此列表的尾端
void add(int index, E element)在此列表中的指定位置插入指定元
void clear()刪除所有元素。
boolean contains(Object o)如果此列表包含指定元素,則返回true 。
boolean isEmpty()如果此列表不包含任何元素,則返回true 。
int size()返回此列表中的元素數。
E get(int index)返回列表中指定位置的元素。
E remove(int index)移除指定位置的元素

練習:

public class TestDemo {
 
    public static void main(String[] args) {
        String str1 = "test1";
        String str2 = "test2";
        String str3 = "test3";
        
        List<String> list = new ArrayList<String>();
        list.add(str1);
        list.add(str1);
        list.add(str2);
        list.add(str3);
        
        
    //下面進行遍歷
        for(String s : list){
            System.out.println(s);
        }
        
    }
 
}

結果:

test1
test1
test2
test3

Set(無序集合)

  • 不依序存放物件
  • 存放物件不可以重複

也因為他是無序的關係,導致了存放物件不可重複,也比List少了幾個方法,例如get。

public class TestSetDemo {
    
    public static void main(String[] args){
        Set<String> set  = new HashSet<String>();
        set.add("test1");
        set.add("test2");
        set.add("test3");
        
        set.remove("test2");
        System.out.println(set.size());
 
    }
}
 
//執行結果:2

Map

API:https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

  • 將物件以key, value的儲存⽅式,放置於Map物件中
  • 使⽤key取得存放的物件
  • 資料的操作都是透過Key操作

 

Map(key, value)

範例:

Map<String, Integer> map =new HashMap<String, Integer>();
public class TestMapDemo {
 
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("test1", 1);
        map.put("test2", 2);
        map.put("test3", 3);
        
        System.out.print(map.get("test2"));
    //執行結果:2
        map.remove("test2");
 
        for(String key : map.keySet()){
            System.out.println(map.get(key));
        }
        //執行結果:3 1
    }
 
}

JAVA I/O

https://docs.oracle.com/javase/7/docs/api/java/io/File.html

檔案操作

File file = new File(fileName); //fileName路徑名稱
file.mkdir(); //建立檔案
file.mkdirs(); //建立檔案,如果路徑上沒有資料夾會一起建立
file.list(); //讀取目錄
file.delete(); //刪除檔案

建立IOUtil工具類例子:

public class IOUtil {
    
    public static void createFolder(String fileName){ //路經參數,所以如果要在home資料夾新增test資料夾,就要傳進"/home/test"
        File file = new File(fileName);
        file.mkdirs();
    }
    
    public static String[] readFolder(String fileName){ //回傳資料夾下面有哪些檔案
        File file = new File(fileName);
        return file.list();
    }
    
    public static void deleteFolder(String fileName){ //刪除檔案
        File file = new File(fileName);
        file.delete();
    }
}

讀取檔案內容

讀取文字檔

  • FileReader: 以Char, String的⽅方式讀取檔案
  • BufferedReader:BifferedReader有一個建構子,就是放入FileReader之後其他任務就可以交由BifferedReader處理。
  • BufferedReader.readLine():透過readLine()讀取文字,readLine()會回傳String
public class IOUtil {   
  public static void readTxtFile(String fileName) {
      FileReader fr = null;
      try {
        fr = new FileReader(fileName); //1.新增FileReader
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
 
      BufferedReader br = new BufferedReader(fr); //2.FileReader交給BufferedReader
      String tmp = null;
      try{
        while((tmp = br.readLine()) != null){ //讀取到沒有資料為止
          System.out.println(tmp); //讀出來的資料會放在tmp一行一行列印出來
        }
      }catch(IOException e){
        e.printStackTrace();
      }finally{   //在IO裡面,要關掉IO,所以在最後關閉
        try {
          br.close();
        } catch (IOException e) { 
          e.printStackTrace();
        }
      }
}

寫入文字檔案

寫入文字檔

  • FileWriter:確認檔案寫入的位置
  • BufferedWriter
    1. BufferedWriter. write(String str):將字串寫進去
    2. BufferedWriter. newLine():跳行
public class IOUtil {
  public static void writeTxtFile(String fileName,List<String> list){
      try {
        FileWriter fw = new FileWriter(fileName);
        BufferedWriter bw = new BufferedWriter(fw);
        for(String str : list){
          bw.write(str);
          bw.newLine(); //繼續往下寫
        }
        bw.flush(); //將記憶體裡面的資料清空
 /*BufferedWriter是緩衝輸入流,意思是調用BufferedWriter的write方法時候。數據是先寫入到緩衝區裡,並沒有直接寫入到目的文件裡。必須用BufferedWriter的flush()方法。這個方法會刷新一下該緩衝流,也就是會把數據寫入到目的文件裡。或者你可以調用BufferedWriter的close()方法,該方法會在關閉該輸入流之前先刷新一下該緩衝流。也會把數據寫入到目的文件裡。原文链接:https://blog.csdn.net/appleml/article/details/41721365*/
      } catch (IOException e) {
        e.printStackTrace();
      } 
    }
 
    public static void copyPictureFile(File source, File dest){
      FileInputStream fis = null;
      FileOutputStream fos = null;
      try{
        fis = new FileInputStream(source);
        fos = new FileOutputStream(dest);
 
        byte[] buffer = new byte[1024];
        int off = 0;
        int len = 0;
 
        while((len = fis.read(buffer)) != -1){
          fos.write(buffer, off, len);
        }
        fos.flush();
      }catch(IOException e){
        e.printStackTrace();
      }finally{
        try {
          fis.close();
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
}

FileInputStream & FileOutputStream

前面介紹的FileReader以及FileWriter都是透過字串類型來讀取或寫入內容,而FileInputStream & FileOutputStream是透過Byte來做讀取以及寫入

  • FileInputStream read(byte[] b):read(讀進來的byte陣列)
  • FileOutputStream
    1. write(byte[] b, int off, int len) :write(將讀進來的byte陣列,起始位置,長度)
    2. flush():寫入
public class IOUtil {
    public static void copyPictureFile(File source, File dest){ //讀取圖檔
      FileInputStream fis = null; 
      FileOutputStream fos = null;
      try{
        fis = new FileInputStream(source); //取得資料位置
        fos = new FileOutputStream(dest);  //寫入位置
 
        byte[] buffer = new byte[1024]; //暫存(可以設定更高)
        int off = 0; //起始位置
        int len = 0;    //長度
 
        while((len = fis.read(buffer)) != -1){ //長度= -1代表讀取結束
          fos.write(buffer, off, len); //寫入檔案
        }
        fos.flush(); //將緩存寫入
      }catch(IOException e){
        e.printStackTrace();
      }finally{
        try {
          fis.close();
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
}

IOUtil實作

結合了上面的完成了較實用的Util類別,檔案目錄結構如下,post.txt要自己隨便加個內容

檔案目錄結構

public class IOUtil {
    
    public static void createFolder(String fileName){
        File file = new File(fileName);
        if(file.mkdirs()){
            System.out.println("新建檔案成功");
        }else{
            System.out.println("新建檔案失敗,檔案有可能已存在");
        }
    }
    
    public static String[] readFolder(String fileName){
        try {
            File file = new File(fileName);
            return file.list();
        } catch (NullPointerException exception) {
            exception.printStackTrace(); //把拋出的expection 全部印出來
        } 
        return null;
    }
    
    public static void deleteFolder(String fileName){
        File file = new File(fileName);
        if(file.delete()){
            System.out.println("刪除檔案成功");
        }else{
            System.out.println("刪除檔案失敗,檔案有可能不存在");
        }
    }
    
    public static List<String> readTxtFile(String fileName) {
        FileReader fr = null;
        List<String> list = new ArrayList<>();
        try {
            fr = new FileReader(fileName);
        } catch (FileNotFoundException e) {
            System.out.println("找不到檔案");
            e.printStackTrace();
            return null;
        }
        
        BufferedReader br = new BufferedReader(fr);
        String tmp = null;
        try{
            while((tmp = br.readLine()) != null){
                list.add(tmp);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
        
    }
    
    public static void writeTxtFile(String fileName,List<String> list){   
        try {
            FileWriter fw = new FileWriter(fileName);
            BufferedWriter bw = new BufferedWriter(fw);
            
            for(String str : list){
                bw.write(str);
                bw.newLine();
            }
            bw.flush();
      bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        } 
                
    }
    
    public static void copyPictureFile(File source, File dest){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try{
            fis = new FileInputStream(source);
            fos = new FileOutputStream(dest);
            
            byte[] buffer = new byte[1024];
            int off = 0;
            int len = 0;
            
            while((len = fis.read(buffer)) != -1){
                fos.write(buffer, off, len);
            }
            fos.flush();
            
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                fis.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }
}

測試程式:

public static void main(String[] args) {
 
        String fileName = "./testFolder";
        //建立資料夾
        IOUtil.createFolder(fileName);
    
        //讀取資料夾目錄
        // "../"代表當前目錄前前一級 "./代表目前目錄得前一級"
        String[] files = IOUtil.readFolder("./codegym");
        for(String name : files){
            System.out.println(name);
        }
        //刪除檔案
        //IOUtil.deleteFolder(fileName);
        //System.out.println("deleteFolder(fileName)執行結束");
        
        //檔案讀取
        List<String> list= IOUtil.readTxtFile("./codegym/post.txt");
        for(String str : list){ //遍歷
            System.out.println(str);
        }
    
        //檔案寫入
        IOUtil.writeTxtFile(fileName + "/textpost.txt",list);
        
        
        //複製圖片
        String source = "./codegym/testImg.png";
        String dest = fileName + "/textImg.png";
        IOUtil.copyPictureFile(new File(source), new File(dest));
        }

完成結果:

終端機輸出:

新建檔案成功
.DS_Store
TestDemo.java
IOUtil.java
post.txt
testImg.png
今天清晨持續受大陸冷氣團影響,各地天氣偏冷,西半部及東北部低溫普遍約11至14℃,其中新竹到雲林、南投及金門有局部10℃以下低溫發生機率,氣象局針對9縣市發布低溫特報。今晨最低溫在嘉義嘉義9.6℃,雲林10℃、彰化、苗栗10.3℃。
 
中央氣象局預報員張承傳指出,今清晨受大陸冷氣團影響,各地天氣偏冷,西半部及東北部低溫普遍約11至14℃。白天起冷氣團稍微減弱,不過溫度回升幅度不多,北部及東北部高溫只有15至18℃,其他地區20至24℃;基隆北海岸及東北部降雨機率偏高,仍容易有短暫雨,而花東及大台北也偶有零星降雨。
 
張承傳指出,明天下半天鋒面接近,西半部水氣增多,明晚到周二清晨降雨最明顯,全台都有陣雨機率,周二白天降雨逐漸趨緩,轉為迎風面北部、東北部為主。
 
周二東北季風增強,屆時北台灣再轉涼,高溫剩下16、17℃。這波東北風從周二影響至周四,不過周三、四水氣較少,僅東半部及北部山區有局部短暫雨,其他地區多雲到晴。周五、周六東北季風減弱,北台灣溫度回升。
 
中央大學大氣系兼任副教授吳德榮在「三立準氣象· 老大洩天機」專欄撰文指出,今晨強冷空氣及「輻射冷卻」加成,本島平地最低氣溫出現在中部:嘉義民雄鄉9.6℃,雲林虎尾、斗南鎮10℃。今晨迎風面雲層仍多,北海岸、東北部有局部降雨,大台北東側則有零星少量飄雨。
 
最新模式模擬顯示,今日白天起強冷空氣稍減弱、氣溫微升,北台偏冷、中南部白天舒適晚仍偏冷;桃園以南晴時多雲,北海岸、大台北東側及東半部偶有零星降雨。今日各地氣溫:北部11至17℃,中部10至24℃,南部11至26℃,東部12至24℃。

執行後檔案目錄結構:

執行後目錄結構