天天看點

Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

Java三大版本

  • JavaSE 标準版 (桌面程式,控制台開發… )
  • JavaME 嵌入式開發 (手機,小家電… )
  • JavaEE E企業級開發 (web端,伺服器開發… )

JDK , JRE , JVM

  • JDK: java Development Kit (Java 開發者工具 , JDK 中包含 JRE)
  • JRE: java Runtime Environment (Java運作環境)
  • JVM: java Virtual Machine (Java虛拟機)

HelloWorld詳解

  1. 随便建立一個檔案夾,存放代碼
  2. 建立一個java檔案
    • 檔案字尾名為 .java
    • HelloWorld.java
    • [注意點] 系統可能沒有顯示檔案字尾名,我們需要手動打開
  3. 編寫代碼
    public class HelloWorld{
    	public static void main(String[] args){
    		System.out.print("Hello,World!");
    	}
    }
               
  4. 編譯 javac java檔案,會生成一個class檔案
  5. 運作class 檔案, java class檔案 (運作class檔案不用加class字尾)
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

Java八大基礎資料類型

資料類型
  • 強類型語言
    • 要求變量的使用要嚴格符合規定,所有變量都必須先定義後才能使用
  • Java的資料類型分為兩大類
    • 基本類型 (primitive type)
    • 引用類型 (reference type)
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO
  1. 整型(byte、short、int、long)

    雖然byte、short、int、long 資料類型都是表示整數的,但是它們的取值範圍可不一樣。

    byte 的取值範圍:-128~127(-2的7次方到2的7次方-1)

    short 的取值範圍:-32768~32767(-2的15次方到2的15次方-1)

    int 的取值範圍:-2147483648~2147483647(-2的31次方到2的31次方-1)

    long 的取值範圍:-9223372036854774808~9223372036854774807(-2的63次方到2的63次方-1)

    由上可以看出 byte、short 的取值範圍比較小,而long的取值範圍時最大的,是以占用的空間也是最多的。int 取值範圍基本上可以滿足我們的日常計算需求了,是以 int 也是我們使用的最多的一個整型類型。

  2. 浮點型(float、double)

    float 和 double 都是表示浮點型的資料類型,它們之間的差別在于精确度的不同。

    float(單精度浮點型)取值範圍:3.402823e+38~1.401298e-45(e+38 表示乘以10的38次方,而e-45 表示乘以10的負45次方)

    double(雙精度浮點型)取值範圍:1.797693e+308~4.9000000e-324(同上)

    double 類型比float 類型存儲範圍更大,精度更高。

    通常的浮點型資料在不聲明的情況下都是double型的,如果要表示一個資料時float 型的,可以在資料後面加上 “F” 。

    浮點型的資料是不能完全精确的,有時候在計算時可能出現小數點最後幾位出現浮動,這時正常的。

  3. 字元型(char)

    char 有以下的初始化方式:

    char ch = ‘a’; // 可以是漢字,因為是Unicode編碼

    char ch = 1010; // 可以是十進制數、八進制數、十六進制數等等。

    char ch = ‘\0’; // 可以用字元編碼來初始化,如:’\0’ 表示結束符,它的ascll碼是0,這句話的意思和 ch = 0 是一個意思。

    Java是用unicode 來表示字元,“中” 這個中文字元的unicode 就是兩個位元組。

    String.getBytes(encoding) 方法擷取的是指定編碼的byte數組表示。

    通常gbk / gb2312 是兩個位元組,utf-8 是3個位元組。

    如果不指定encoding 則擷取系統預設encoding 。

  4. boolean 沒有什麼好說的,它的取值就兩個:true 、false 。

類型轉換

  • 由于Java是強類型語言,是以要進行有些運算的時候,需要用到類型轉換

    低 -------------------------------------------------------> 高

    byte,short,char --> int --> long --> float --> double

  • 運算中,不同類型的資料先轉換為同一類型,然後進行運算
  • 強制類型轉換
  • 自動類型轉換
package com.byxx.yunan;

import java.util.HashMap;
import java.util.concurrent.*;

/**
 * @Author yww
 * @CreateTime 2020-10-25
 */
public class Test {
    public static void main(String[] args){

        int i = 128;
        byte b = (byte) i; //強制轉換記憶體溢出, Byte最大值為127 ,最小值為-128

        //輸出值 為 -128
        System.out.println(b);

        //自動轉換
        double d = i;
        System.out.println(d);

        /*
          注意點:
            1. 不能對布爾值進行轉換
            2. 不能把對象類型轉換為不相幹的類型
            3. 在把高容量轉換到低容量時,需要強制轉換,反正,自動轉換
            4. 轉換的時候可能存在記憶體溢出,或者精度問題!
         */

        System.out.println((int)23.7);//23
        System.out.println((int)-45.89f);//-45
    }
}

           
注意 操作比較大的數的時候,記憶體溢出問題
package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test2 {
    public static void main(String[] args) {
        //操作比較大的數的時候,注意溢出問題
        //JDK7新特性,數字直接可以用下劃線分割
        int money = 10_0000_0000;
        int years = 20;
        int total = money * years;//-1474836480 , 記憶體溢出

        long total2 = money * years;//-1474836480 , 先是兩個int類型運算 得出結果還是int類型 (結果已經出問題了,再轉long也是不行)

        long total3 = money * ((long)years);//20000000000 , 先把一個數轉為long
        
        System.out.println(total3);
    }
}
           

變量 ,常量 , 作用域

  • 預設初始化值:
    • 數字: 0 0.0
    • char: \u0000
    • boolean: false
    • 引用:null
package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test3 {

    //靜态常量
    static final String str = "1";

    //類變量,靜态變量
    static String msg = "123";

    //執行個體變量: 從屬于對象,如果不自行初始化值, 則拿 類型的預設值
    //int 0,以此類推,除了基本類型,其餘的預設都是 null ,布爾值為false
    String name;
    int age;

    public static void main(String[] args) {
        //局部變量
        int i = 1;

        //new 對象
        Test3 test = new Test3();
        System.out.println(test.name+"\n"+test.age);
    }
}
           

運算符

  • 算術運算符:+,-,*,/,%,++,–
  • 指派運算符:=
  • 關系運算符:>,<,>=,<=,==,!=,instanceof
  • 邏輯運算符:&&,||,!
  • 位運算符:&,|,^,~,>>,>>>
  • 條件運算符:?,:
  • 擴充指派運算符:+=,-=,*=,/=

算術運算符

package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test4 {
    public static void main(String[] args) {
        //++  --   自增,自減    一進制運算符
        int a = 3;

        int b = a++; //先給b指派,再自增

        int c = ++a; //先自增,再指派

        System.out.println(a);// 5
        System.out.println(b);// 3
        System.out.println(c);// 5

        //幂運算  2^3  2*2*2 = 8
        double pow = Math.pow(2,3);//java中的幂運算
        System.out.println(pow);
    }
}
           

邏輯運算符

package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test5 {
    public static void main(String[] args) {
        //& 與(and) , | 或(or) , ! 非(取反)
        boolean a = true;
        boolean b = false;

        System.out.println(a&&b);//false    邏輯與運算,兩個變量都為true,結果才為true
        System.out.println(a||b);//true     邏輯或運算,兩個變量有一個為true,結果才為true
        System.out.println(!(a&&b));//true  如果是真,則為假  如果是假,則為真

        //短路運算
        System.out.println(b&&a);//第一位數為false則不執行後面操作,輸出結果為false

        //驗證: (短路運算)
        int i = 5;
        // i>6 = false  &&  i++>7
        System.out.println((i>6) && (i++)>7);
        //根據 算術運算符定律  i++ 如果執行了,則i=6
        System.out.println(i);//輸出結果為5,驗證了短路運算,前者為false,後者不執行
    }
}
           

位運算符

package com.byxx.yunan.test;

import javax.sound.midi.Soundbank;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test6 {
    public static void main(String[] args) {
        /*
            A = 0011 1100
            B = 0000 1101
            -----------------
            A&B = 0000 1100     位運算(與運算),同級位,兩個值相等則為相等值,否則為0
            A|B = 0011 1101     位運算(或運算),同級位,
            A^B = 0011 0001     位運算(異或運算),同級位,兩個值相等則為0,不相等則為1
             ~B = 1111 0010     (取反運算),0為1,1為0
         */

        //左移運算 (第一個數值 乘 2的第二個數值次方)
        System.out.println(3*2);
        System.out.println(3<<1);//3 * 2的一次方(3乘2的一次方)   3 * 2 = 6
        System.out.println(3<<2);//3 * 2的二次方(3乘2的二次方)   3 * (2*2) = 12
        System.out.println(3<<3);//3 * 2的三次方(3乘2的三次方)   3 * (2*2*2) = 24

        //右移運算 (第一個數值 除 2的第二個數值次方)
        System.out.println("-------------------------");
        System.out.println(4>>1);//4 / 2的一次方(4除2的一次方)   4 / 2 = 2
        System.out.println(4>>2);//4 / 2的二次方(4除2的二次方)   4 / (2*2) = 1
        System.out.println(4>>3);//4 / 2的三次方(4除3的三次方)   4 / (2*2*2) = -4

    }
}

           

條件運算符 (三元運算符)

package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test8 {
    public static void main(String[] args) {

        int age = 22;
        //普通 三元運算符
        String type1 = age>18 ? "成年" : "未成年"; //輸出結果為 成年

        //嵌套 三元運算符
        String type2 = age>30 ? "成年" : (age==22) ? "我22歲啦" : "未成年";//輸出結果為 我22歲啦
    }
}
           

擴充指派運算符

package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test7 {
    public static void main(String[] args) {
        int a = 10;
        int b = 2;

        a+=b;//a = a + b;
        a-=b;//a = a - b;
        a*=b;//a = a * b;
        a/=b;//a = a / b;

        //字元串連接配接符  + , String
        System.out.println(""+a+b);//字元串在前,則輸出字元串連接配接 結果為 102,要想結果正确加括号即可  ""+(a+b)

        System.out.println(a+b+"");//從左開始運算,a+b= 12 加字元串 = 12
    }
}
           

JavaDoc生成文檔

  • cmd指令 javadoc -encoding UTF-8 -charset UTF-8 Test9.java
    需要文檔注釋
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO
  • 生成JavaAPI文檔

Switch 多選擇結構

  • switch case 語句判斷一個變量與系列值中某個值是否相等,每個值稱為一個分支
  • switch 語句中的變量類型可以是:
    • byte, short, int 或者char
    • 從Java SE7 開始 switch支援字元串String 類型了
    • 同時 case 标簽必須為字元串常量或字面量
package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test9 {

    public static void main(String[] args) {
        byte a = 0;
        short b = 1;
        int c = 2;
        char d = 'A';
        String str = "高達";
        //JDK 7 ,表達式結果可以是字元串!
        //字元的本質還是數字

        switch (str){
            case "張三":
                System.out.println("張三");
                break;//沒有寫break會出現switch穿透
            case "李四":
                System.out.println("李四");
                break;
            case "高達":
                System.out.println("這裡是高達!");
                break;
            default:
                System.out.println("what are you? 弄啥嘞?");
        }
    }
}

           

驗證字元本質還是數字 (檢視編譯後源碼)

Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO
編譯後class檔案
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.byxx.yunan.test;

public class Test9 {
    public Test9() {
    }

    public static void main(String[] args) {
        byte a = false;
        short b = true;
        int c = true;
        char d = true;
        String str = "高達";
        byte var7 = -1;
        switch(str.hashCode()) {
        case 774889:
            if (str.equals("張三")) {
                var7 = 0;
            }
            break;
        case 842061:
            if (str.equals("李四")) {
                var7 = 1;
            }
            break;
        case 1265638:
            if (str.equals("高達")) {
                var7 = 2;
            }
        }

        switch(var7) {
        case 0:
            System.out.println("張三");
            break;
        case 1:
            System.out.println("李四");
            break;
        case 2:
            System.out.println("這裡是高達!");
            break;
        default:
            System.out.println("what are you? 弄啥嘞?");
        }

    }
}

           

循環結構

  • while 循環
  • do … while 循環
  • for 循環
  • 增強 for 循環
    • while 循環
      • 隻要布爾表達式為true,循環就會一直執行下去,false則退出
      int a = 0;
      while (a<10){
          a++;
          System.out.println(a);
      }
                 
    • do … while 循環
      • do … while 和 while 循環相似,不同的是,do … while 循環至少會執行一次。
      • while 和 do … while 的差別:
        • while 先判斷,後執行。do … while 先執行,後判斷!
        • do … while 總是保證循環體至少會被執行一次!這是他們的主要差别。
      int a = 0;
      do{
          a++;
          System.out.println(a);
      }while(a<10);
                 
    • for 循環
      • for 循環執行的次數是在執行前就确定的。文法格式如下:
        for(初始化; 布爾表達式; 更新){
        	//代碼語句
        }    
                   
      • for 循環 的 死循環寫法
        for(;;){
            
        }
                   
      • 列印99乘法表
        package com.byxx.yunan.test;
        
        /**
         * @Author yww
         * @CreateTime 2021-02-03
         */
        public class Test10 {
        
            public static void main(String[] args) {
                /*
                    列印99乘法表
                    1*1=1
                    2*1=2	2*2=4
                    3*1=3	3*2=6	3*3=9
                    4*1=4	4*2=8	4*3=12	4*4=16
                    5*1=5	5*2=10	5*3=15	5*4=20	5*5=25
                    6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36
                    7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49
                    8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64
                    9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81
        
                    步驟解析:
                        1. 我們先列印第一列
                        2. 去掉重複項 b <= a
                        3. 調整樣式
                 */
                for(int a=1;a<=9;a++){
                    for(int b=1;b<=a;b++){
                        System.out.print(a+"*"+b+"="+(a*b)+"\t");
                    }
                    System.out.println();
                }
        
            }
        }
                   
    • 增強 for 循環
      • 主要用于周遊數組和集合的增強型 for 循環
      int[] numbers = {10,20,30,40,50};
      
      for(int x: numbers){
          System.out.println(x);
      }
                 

Break ,Continue

  • break 在任何循環語句的主體部分, 均可用break控制循環的流程。break用于強制退出循環,不執行循環中剩餘的語句。(break語句也可以在switch中使用)
  • continue 語句用在循環語句體中,用于終止某次循環過程,即跳出循環體中尚未執行的語句,接着進行下一次是否執行循環的判定。

方法重載

  • 方法名必須相同
  • 參數清單必須不同
  • 傳回值一緻或者相同 (傳回值不能決定方法是不是重載)
//重載
public String appendMsg(String str1,int a){
    return str1+a;
}

//重載
public Integer appendMsg(int a,int b){
    return a+b;
}

//原型
public String appendMsg(String str1,String str2){
    return str1+str2;
}
           

可變參數

  • 在方法聲明中,在指定參數類型後加一個省略号(…)
  • 一個方法中隻能指定一個可變參數,它必須是方法的最後一個參數。任何普通的參數必須在它之前聲明。
package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-03
 */
public class Test12 {
    public static void main(String[] args) {
        Test12 t1 = new Test12();
        t1.getName("1","2","3");//123
        t1.getName("1","4");//14
    }

    //可變參數
    public String getName(String... names){
        StringBuffer sb = new StringBuffer();
        for(String str : names){
            sb.append(str);
        }
        return sb.toString();
    }
}
           

Math 數學工具類

  • 平常基本方法:
    • Math.abs(); 擷取絕對值
    • Math.ceil(); 向上取整
    • Math.floor(); 向下取整
    • Math.round(); 四舍五入
package com.byxx.yunan.test.arrays;

/**
 *
 * @Author yww
 * @CreateTime 2021-02-07
 */
public class Test7 {
    public static void main(String[] args) {
        /*
           Math 數學工具類, 平常基本方法使用
            public static double abs(double num):擷取絕對值。有多種重載
            public static double ceil(double num):向上取整
            public static double floor(double num):向下取整
            public static long round(double num):四舍五入
         */

        //擷取絕對值
        System.out.println(Math.abs(3.14));//3.14
        System.out.println(Math.abs(0));//0
        System.out.println(Math.abs(-3.14));//3.14

        //向上取整
        System.out.println(Math.ceil(3.9));//4.0
        System.out.println(Math.ceil(3.0));//3.0
        System.out.println(Math.ceil(3.1));//4.0

        //向下取整
        System.out.println(Math.floor(3.9));//3.0
        System.out.println(Math.floor(3.1));//3.0
        System.out.println(Math.floor(3.0));//3.0

        //四舍五入
        System.out.println(Math.round(3.5));//4
        System.out.println(Math.round(3.4));//3
        System.out.println(Math.round(3.6));//4

    }
}
           

Random 随機數工具類

package com.byxx.yunan.test.arrays;

import java.util.Random;

/**
 * @Author yww
 * @CreateTime 2021-02-07
 */
public class Test8 {
    public static void main(String[] args) {
        //建立随機數
        Random random = new Random();
        for (int i = 0; i < 100; i++) {
            int num = random.nextInt(5);// 範圍是 0-5, 實際取值範圍是 0-4
//            System.out.println(num);
        }

        //需求: 随機數實際取值 從1開始

        for (int i = 0; i < 100; i++) {
            int num = random.nextInt(9)+1;// 範圍是 (0-9)+1, 原範圍是0-8, +1後實際取值範圍是 1-9
            System.out.println(num);
        }

    }
}
           

數組

數組詳解

  • 必須聲明數組變量,才能在程式中使用數組,使用new操作符來建立數組
    int[] arrays1 = new int[3];//首標明義方式
    int arrays3[] = new int[3];//效果相同,但不是首選
    int[] arrays2 = {1,2,3};
               
  • 數組的元素是通過索引通路的,數組索引從0開始
  • 擷取數組長度:
    arrays.length
               
  • 數組的四個基本特點
    • 其長度是确定的。數組一旦被建立,它的大小就是不可以改變的。
    • 其元素必須是相同類型,不允許出現混合類型。
    • 數組中的元素可以是任何資料類型,包括基本類型和引用類型。
    • 數組變量屬于引用類型,數組也可以看成是對象,數組中的每個元素相當于該對象的成員變量。數組本身就是對象,Java中對象是在堆中的,是以數組無論儲存原始類型還是其他對象類型,數組對象本身是在堆中的。
擷取數組中的最大值
package com.byxx.yunan.test;

/**
 * @Author yww
 * @CreateTime 2021-02-04
 */
public class Test {

    public static void main(String[] args) {
        //查詢數組中最大值
        int[] arrays = {1,5,2,8,3};

        int max = 0;
        for(int a: arrays){
            if(a>max){
                max = a;
            }
        }
        System.out.println(max);//8
    }
}
           
反轉數組
  1. 第一種方法
package com.byxx.yunan.test.arrays;

import javax.sound.midi.Soundbank;
import java.util.Arrays;

/**
 * @Author yww
 * @CreateTime 2021-02-04
 */
public class Test1 {
    public static void main(String[] args) {
        //反轉數組
        int[] arrays = {1,2,3,4,5};

        int[] newArrays = new int[arrays.length];

        int initLength = arrays.length-1;

        //第一種方法
        int index = 0;
        for(int a=initLength; a>=0; a--){
            newArrays[index] = arrays[a];
            index++;
        }
        System.out.println(Arrays.toString(newArrays));
        
    }
}
           
  1. 第二種方法
package com.byxx.yunan.test.arrays;

import javax.sound.midi.Soundbank;
import java.util.Arrays;

/**
 * @Author yww
 * @CreateTime 2021-02-04
 */
public class Test1 {
    public static void main(String[] args) {
        //反轉數組
        int[] arrays = {1,2,3,4,5};

        int[] newArrays = new int[arrays.length];

        int initLength = arrays.length-1;

        //第二種方法
        for(int a = 0,b = initLength; a <=initLength; a++,b--){
            newArrays[a] = arrays[b];
        }
        System.out.println(Arrays.toString(newArrays));

    }
}

           

多元數組

  • 多元數組可以看成是數組的數組,比如二維數組就是一個特殊的一維數組,其每一個元素都是一個一維數組。
  • 二維數組
    package com.byxx.yunan.test.arrays;
    
    /**
     * @Author yww
     * @CreateTime 2021-02-04
     */
    public class Test2 {
        public static void main(String[] args) {
            //建立二維數組
            //int[][] a = new int[2][5];
    
            int[][] a = {{1,2},{3,4},{5,6}};
    
            for(int i=0;i<a.length;i++){
                for (int j=0;j<a[i].length;j++){
                    System.out.print(a[i][j]+"\t");
                }
                System.out.println();
            }
            /*
            輸出結果:
                1	2
                3	4
                5	6
             */
        }
    }
               
  • 二維數組結構解析
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

Arrays 工具類

  • sort 用法 (升序,降序)
    Integer[] arrays = {5,2,4,3,8};
    String[] strs = {"aaa","bbb","ccC","eee","ddd"};  //字母也可以,預設按26個英文字母升序排列
    //升序 排序
    Arrays.sort(arrays);
    System.out.println(Arrays.toString(arrays));//[2, 3, 4, 5, 8]
    
    //降序排序
    Arrays.sort(arrays,Collections.reverseOrder());
    System.out.println(Arrays.toString(arrays));//[8, 5, 4, 3, 2]
               
  • 冒泡排序
    package com.byxx.yunan.test.arrays;
    
    import java.util.Arrays;
    
    /**
     * @Author yww
     * @CreateTime 2021-02-04
     */
    public class Test4 {
    
        public static void main(String[] args) {
            /*
             冒泡排序
                1.比較數組中,兩個相鄰的元素,如果第一個數比第二個數大,我們就交換他們的位置
                2.每一次比較,都會産生一個最大,或者最小的數字
                3.下一輪則可以少一次排序
                4.一次循環,直到結束
             */
    
            int[] arrays = {1,3,2,1,7,4,8};
            //臨時變量
            int temp = 0;
            boolean flag = false;//是否交換的标志
    
            for (int i = 0; i < arrays.length-1; i++) {
                // 每次周遊标志位都要先置為false,才能判斷後面的元素是否發生了交換
                flag = false;
                for (int j = 0; j < arrays.length-1-i; j++) {
                    if(arrays[j+1] > arrays[j]){ // > 大于為 降序  , < 小于 為升序
                        temp = arrays[j];
                        arrays[j] = arrays[j+1];
                        arrays[j+1] = temp;
                        flag = true;
                    }
                }
                // 判斷标志位是否為false,如果為false,說明後面的元素已經有序,就直接return
                if(!flag){
                    break;
                }
            }
    
            System.out.println(Arrays.toString(arrays));//[8, 7, 4, 3, 2, 1, 1]
    
        }
    }
               

Object ,Objects

  • Object.equals() Object為null,會報空指針異常
  • Objects.equals(a,b) a為null,不會出現空指針異常
    package com.byxx.yunan.test.oop;
    
    import java.util.Objects;
    
    /**
     * @Author yww
     * @CreateTime 2021-02-07
     */
    public class Test1 {
        public static void main(String[] args) {
    
            String str = null;
            //普通equals() 不允許第一個值null,否則報錯
            boolean flagA = str.equals("123");
            System.out.println(flagA);//報錯,空指針異常
    
            //Objects.equals(a,b); 不會報錯, 允許第一個值為null,防止空指針
            boolean flagB = Objects.equals(str, "123");
            System.out.println(flagB);
    
        }
    }
               

日期

Date

  • Date date = new Date(); 無參構造,擷取目前系統日期時間
  • Date date = new Date(long date); 有參構造,傳遞毫秒數,把毫秒轉換為Date日期
  • date.getTime(); 把日期轉換為毫秒(相當于System.currentTimeMillis()) ,

    ​ 傳回 1970年 1月 1日 00:00:00 GMT 以來此表示 Date 對象表示的毫秒數

package com.byxx.yunan.test.oop;

import com.sun.org.apache.bcel.internal.generic.NEW;

import java.util.Date;

/**
 * @Author yww
 * @CreateTime 2021-02-07
 */
public class Test2 {
    public static void main(String[] args) {
        demo1();
        demo2();
        demo3();
    }


    /*
        Date 的無參構造方法
            new Date(); 擷取目前系統日期時間
     */
    private static void demo1(){
        Date date = new Date();
        System.out.println(date);//Sun Feb 07 15:30:24 CST 2021
    }

    /*
        Date 的有參構造方法
            new Date(long date); 傳遞毫秒值,把毫秒轉換為Date日期
    */
    private static void demo2(){
        Date date = new Date(0L);//初始日期時間
        System.out.println(date);//Thu Jan 01 08:00:00 CST 1970
    }

    /*
        Date 類的成員方法
            long getTime() 把日期轉換為毫秒(相當于System.currentTimeMillis())
                傳回 1970年 1月 1日 00:00:00 GMT 以來此表示 Date 對象表示的毫秒數
     */
    private static void demo3(){
        Date date = new Date();
        long time = date.getTime();
        System.out.println(time);
    }

}
           

SimpleDateFormat

  1. SimpleDateFormat 常用方法
    • format(); 将日期轉為字元串格式
    • parse(); 将字元串轉為日期格式
    package com.byxx.yunan.test.oop;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * java.text.SimpleDateFormat:是日期/時間格式化子類的抽象類
     * 作用:
     *      格式化(日期--轉--文本) (文本--轉--日期)
     * 成員方法:
     *      String format(Date date) 按照指定的模式,把Date日期,格式化為符合模式的字元串
     *      Date parse(String source) 把符合模式的字元串,解析為Date日期
     * @Author yww
     * @CreateTime 2021-02-08
     */
    public class Test3 {
        public static void main(String[] args) throws ParseException {
    
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:ss:mm");
    
            //日期轉字元串   format()
            Date date = new Date();
            String timeStr = sdf.format(date);
            System.out.println(timeStr);//2021-02-08 09:55:06
    
            //字元串轉Date  parse()
            String nowDate = "2021-02-08 09:28:06";
            Date timeDate = sdf.parse(nowDate);
            System.out.println(timeDate);//Mon Feb 08 09:06:28 CST 2021
    
        }
    }
               

Calendar 月曆類

  • Calendar類的成員方法
    • public int get (int field); 傳回該月曆字段的值
    • public void set (int field,int value); 将給定的月曆字段設定為定值
    • public abstract void add (int field,int amount); 根據月曆的規則,為給定的月曆字段添加或減去指定的時間量
    • public Date getTime (); 傳回一個表示此Calendar的值 (從曆元到現在的毫秒偏移量) 的Date對象
  • 成員方法的參數
    • int field; 月曆類的字段,可以使用Calendar類的靜态成員變量擷取
    • public static final int YEAR = 1; 年
    • public static final int MONTH = 2; 月 西方的0-11,東方的1-12,是以結果+1
    • public static final int DATE = 5; 月中的某一天
    • public static final int DAY_OF_MONTH = 5;月中的某一天
    • public static final int HOUR = 10; 時
    • public static final int MINUTE = 12; 分
    • public static final int SECOND = 13; 秒
package com.byxx.yunan.test.oop;

import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.util.Calendar;
import java.util.Date;

/**
 * Calendar類的成員方法:
 *      public int get(int field); 傳回給月曆字段的值。
 *      public void set(int field,int value); 将給定的月曆字段設定為定值
 *      public abstract void add(int field,int amount); 根據月曆的規則,為給定的月曆字段添加或減去指定的時間量
 *      public Date getTime(); 傳回一個表示此Calendar的值 (從曆元到現在的毫秒偏移量)的Date對象
 *
 * 成員方法的參數:
 *      int field:月曆類的字段,可以使用Calendar類的靜态成員變量擷取
 *      public static final int YEAR = 1; 年
 *      public static final int MONTH = 2; 月 //西方的0-11, 東方的1-12, 是以結果+1
 *      public static final int DATE = 5; 月中的某一天
 *      public static final int DAY_OF_MONTH = 5; 月中的某一天
 *      public static final int HOUR = 10; 時
 *      public static final int MINUTE = 12; 分
 *      public static final int SECOND = 13; 秒
 */
public class Test4 {
    public static void main(String[] args) {
        //月曆類
        Calendar c = Calendar.getInstance();

        //沒有列印記憶體位址,代表重寫了toString()方法
        //java.util.GregorianCalendar[time=1612747829597,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2021,MONTH=1,WEEK_OF_YEAR=7,WEEK_OF_MONTH=2,DAY_OF_MONTH=8,DAY_OF_YEAR=39,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=9,HOUR_OF_DAY=9,MINUTE=30,SECOND=29,MILLISECOND=597,ZONE_OFFSET=28800000,DST_OFFSET=0]
        System.out.println(c);

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;//西方的0-11, 東方的1-12, 是以結果+1
        int date = c.get(Calendar.DATE);
        System.out.println(year+"年 "+month+"月 "+date+"号");

        //給指定月曆字段指派  calendar.get(int field);
        c.set(Calendar.YEAR,2088);
        System.out.println(c.get(Calendar.YEAR));// 輸出: 2088

        //根據月曆的規則,為給定的月曆字段添加或減去指定的時間量  calendar.add(int field);
        c.add(Calendar.YEAR,-2);//減兩年
        System.out.println(c.get(Calendar.YEAR));// 輸出:在2088年上減兩年   2086

        c.add(Calendar.MONTH,3);//加三月
        System.out.println(c.get(Calendar.MONTH)+1);// 輸出:5

    }
}
           

面向對象

面向對象特征

  • 面向對象程式設計的本質就是:以類的方式組織代碼,以對象的組織(封裝)資料
  • 抽象
  • 三大特征:
    • 封裝
      • 提高了程式的安全性,保護資料
      • 隐藏了代碼的實作細節
      • 統一接口
      • 系統可維護性增加
    • 繼承
      • extends 的意思是 “擴充” 。子類是父類的擴充
      • Java中的 類 隻有單繼承,沒有多繼承!,接口可以多繼承。(一個兒子隻有一個親爸爸(單繼承))
      • 類被 final 修飾後不能被繼承,因為 final 不可更改,子類無法重寫父類方法
    • 多态
      • 父類的引用指向子類 (父 new 子)
      • 多态存在的條件:
        • 有繼承關系
        • 子類重寫父類方法
        • 父類引用指向子類對象
        package com.byxx.yunan.test.arrays;
        
        /**
         * @Author yww
         * @CreateTime 2021-02-04
         */
        public class Test6 {
            public static void main(String[] args) {
        
                //Student 能調用自身和父類的方法
                Student student = new Student();
        
                //Person 隻能調用自身的方法, 不可調用子類的方法
                Person person = new Student();
        
                //驗證父 new 子,類全部都隐式繼承了Object
                Object object = new Student();
            }
        }
        
        //學生  繼承 人
        class Student extends Person{
        
        }
                   
值傳遞,引用傳遞
package com.byxx.yunan.test.arrays;

/**
* @Author yww
* @CreateTime 2021-02-04
*/
public class Test5 {
  public static void main(String[] args) {

      String name = "李四";

      change(name);//值傳遞,原值不變
      System.out.println(name);//輸出結果為:李四

      Person person = new Person();
      person.name = "李四";

      changePerson(person);
      System.out.println(person.name);//輸出結果為:王五

  }
  //值傳遞
  public static void change(String name){
      name = "張三";
  }

  //引用傳遞: 對象,本質還是值傳遞
  public static void changePerson(Person person){
      //person是一個對象, 指向的 ---> Person person = new Person(); 這是一個具體的對象,可以改變屬性!
      person.name = "王五";
  }

}

//person類
class Person{
  String name;
}
           
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

super,this

super注意點:

​ 1. super 調用父類的構造方法,必須在構造方法的第一個

​ 2. super 必須隻能出現在子類的方法或者構造方法中

​ 3. super 和 this 不能同時調用構造方法

VS this:

  1. 代表的對象不同:

    ​ this:本身調用者這個對象

    ​ super:代表父類對象的應用

    1. 前提:

    ​ this:沒有繼承也可以使用

    ​ super:隻能在繼承條件中才可以使用構造方法

    1. 構造方法:

    ​ this() ; 本身的構造

    ​ super() ; 父類的構造

重寫

重寫:需要有繼承關系,子類重寫父類的方法!
  1. 方法名必須相同
  2. 參數清單必須相同
  3. 修飾符:範圍可以擴大但不能縮小 public > protected > default > private
  4. 抛出的異常:範圍,可以被縮小,但不能擴大 ClassNotFoundException --> Exception (大)
重寫:子類的方法和父類必須一緻:方法體不同!

為什麼需要重寫 ?

​ 父類的功能,子類不一定需要,或者不一定滿足!

static 關鍵字詳解

package com.byxx.yunan.test.arrays;

/**
 * @Author yww
 * @CreateTime 2021-02-04
 */
public class User {

    //2
    {
        System.out.println("匿名代碼塊");
    }

    //1  隻執行一次
    static {
        System.out.println("靜态代碼塊");
    }

    //3
    public User(){
        System.out.println("構造方法");
    }

    public static void main(String[] args) {
        /*
            建立 User 對象時, 先執行  靜态代碼塊, 再執行 匿名代碼塊, 最後執行 構造方法
         */
        User user = new User();

        /*
            第二次建立 User 對象,先執行 匿名代碼塊, 再執行 構造方法,
                注意: 第二次建立 該對象 不再 執行靜态代碼塊, 因為 static 修飾 隻執行一次
         */
        User user2 = new User();
    }
}
           

抽象

  • 抽象類不能執行個體化(new),隻能靠子類去實作它
  • 抽象類中可以寫普通的方法
  • 抽象方法必須在抽象類中
  • 抽象方法存在構造器

1. 抽象類存在的意義?

​ 更利于代碼的維護性和重用,提高開發效率。

2. 驗證理論

package com.byxx.yunan.test.oop;

//abstract 抽象類: 類 extends 單繼承~  (接口可以多繼承)
public abstract class Action {

 //abstract, 抽象方法, 隻有方法名字, 沒有方法的實作!
 public abstract void sayHi();

 //普通方法
 public String getName(){
     return "張三";
 }

 //1. 抽象類不能執行個體化(new), 隻能靠子類去實作它
 //2. 抽象類中可以寫普通的方法
 //3. 抽象方法必須在抽象類中
 //4. 抽象方法存在構造器
 /*
    抽象類存在的意義?
       更利于代碼維護和重用,提高開發效率
  */
}

//抽象類的所有方法, 繼承了它的子類, 都必須要實作它的抽象方法, 除非子類也是抽象
class ChildActionB extends Action{

 @Override
 public void sayHi() {

 }
}

//子類抽象, 不需要重寫 父抽象類 的方法
abstract class ChildActionC extends Action{

}
           

接口

  • interface 關鍵字定義接口,接口中可以多繼承
  • 接口中定義變量 實際為 常量 預設加上 public static final
  • 接口中的所有定義其實都是抽象的 預設加上 public abstract
  • 實作接口必須實作接口中的所有方法,因為接口中的方法 都是抽象的
  • 接口不能被執行個體化,因為接口中沒有構造方法
  • implement 可以實作多個接口
package com.byxx.yunan.test.oop;

//interface  關鍵字定義接口, 接口中可以多繼承
public interface UserService {

    //接口中定義變量 實際為常量  預設加上 public static final
    int AGE = 99;


    //接口中的所有定義其實都是抽象的  預設加上 public abstract
    public abstract String getName();

    //等價 public abstract Integer getAge();
    public Integer getAge();

    //等價 public abstract void sayHello();
    void sayHello();

}
           

N種内部類

  • 成員内部類
    import javax.sound.midi.Soundbank;
    
    /**
     * 外部類
     * @Author yww
     * @CreateTime 2021-02-05
     */
    public class Outer {
    
        //成員内部類
        class Inner{
            public void say(){
                System.out.println("這是成員内部類的方法");
            }
        }
    }
               
  • 靜态内部類
    import javax.sound.midi.Soundbank;
    
    /**
     * 外部類
     * @Author yww
     * @CreateTime 2021-02-05
     */
    public class Outer {
    
        //靜态内部類
        static class Inner2{
            public void say(){
                System.out.println("這是靜态内部類的方法");
            }
        }
    }
               
  • 局部内部類
    import javax.sound.midi.Soundbank;
    
    /**
     * 外部類
     * @Author yww
     * @CreateTime 2021-02-05
     */
    public class Outer {
    
        //局部内部類
        class Inner{
            public void say(){
                System.out.println("這是局部内部類的方法");
            }
        }
    }
               
  • 匿名内部類
    package com.byxx.yunan.test.oop;
    
    import com.sun.org.apache.bcel.internal.generic.NEW;
    
    /**
     * 外部類
     * @Author yww
     * @CreateTime 2021-02-05
     */
    public class Outer {
        public static void main(String[] args) {
    
            //匿名内部類
            new PersonService(){
                @Override
                public void hello() {
    
                }
            };
            
        }
    
    }
    
    interface PersonService{
        void hello();
    }
    
               

異常

Error 和 Exception

  • Error
    • Error類對象由 Java 虛拟機生成并抛出,大多數錯誤與代碼編寫者所執行的操作無關。
  • Exception
    • Exception異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度盡可能避免這類異常的發生。

Error 和 Exception 的差別 :

​ Error 通常是災難性的緻命的錯誤,是程式無法控制和處理的,當出現這些異常時,Java虛拟機 (JVM) 一般會選擇終止線程;

​ Exception 通常情況下是可以被程式處理的,并且在程式中應該盡可能的去處理這些異常。

捕獲和抛出異常

  • 異常處理機制
    • 抛出異常
    • 捕獲異常
  • 異常處理五個關鍵字
    • try (監控區域)
    • catch (想要捕獲的異常類型!) 捕獲異常
    • finally (一般用于關閉資源)
    • throw (主動抛出異常,一般在 方法中 使用)
    • throws (主要抛出異常,一般在 方法上 使用)
    package com.byxx.yunan.test.exception;
    
    /**
     * @Author yww
     * @CreateTime 2021-02-05
     */
    public class Test1 {
        public static void main(String[] args) {
    
            int a = 1;
            int b = 0;
    
            //假設要捕獲多個異常:從小到大
    
            try{//監控區域
    
                new Test1().test(1,0);
    
            }catch (Exception e){ //catch(想要捕獲的異常類型!) 捕獲異常
                System.out.println("Exception");
            }catch (Throwable t){
                System.out.println("Throwable");
            }finally {
                System.out.println("finally");
            }
            //finally 可以不要, 假設IO,資源操作時,則需要finally 用于關閉資源
        }
    
        //假設這方法中,處理不了這個異常。 方法上 抛出異常 ,使用 throws
        public void test(int a,int b) throws ArithmeticException{
    
            if(b == 0){//throw
                throw new ArithmeticException();//主動抛出的異常,一般在 方法中 使用
            }
    
        }
    }
               

自定義異常

自定義異常
package com.byxx.yunan.test.exception;

/**
 * 自定義的異常類
 * @Author yww
 * @CreateTime 2021-02-05
 */
public class MyException extends Exception{

    //傳遞數字 > 10
    private int detail;

    public MyException(int a){
        this.detail = a;
    }

    //toString: 異常的列印資訊
    @Override
    public String toString() {
        return "MyException{ detail=" + detail +"} ";
    }
}
           
自定義異常使用
package com.byxx.yunan.test.exception;

/**
 * @Author yww
 * @CreateTime 2021-02-05
 */
public class ExceptionMain {
    public static void main(String[] args) throws MyException {
        //調用getNumber方法
        new ExceptionMain().getNumber(11);
    }

    public int getNumber(int num) throws MyException {
        if(num>10){//傳遞值 > 10 抛出自定義異常
            throw new MyException(num);
        }
        return num;
    }
}
           

System類

  • public static long currentTimeMillis(); 傳回以毫秒為機關的目前時間
  • public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); 将數組中指定的資料拷貝到另一個數組中
package com.byxx.yunan.test.string;

import java.util.Arrays;

/**
 * @Author yww
 * @CreateTime 2021-02-10
 */
public class Test1 {
    public static void main(String[] args) {

        /*
           System.currentTimeMillis(); 計算循環1000次後所需要的執行時間 (毫秒為機關)
         */
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("程式共用時: "+(endTime - startTime)+"毫秒");

        /*
           System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
           将數組中指定的資料拷貝到另一個數組中
           參數:
              src - 源數組
              srcPos - 源數組中的起始位置
              dest - 目标數組
              destPos - 目标資料中的起始位置
              length - 要複制的數組元素的數量
         */
        int[] arrays1 = {1,2,3,4,5,6};
        int[] arrays2 = {7,8,9,1,2,3};

        System.arraycopy(arrays1,0,arrays2,0,3);

        System.out.println(Arrays.toString(arrays1));//輸出: [1,2,3,4,5,6]

        System.out.println(Arrays.toString(arrays2));//輸出: [1,2,3,1,2,3]

    }
}
           

StringBuilder

String 類

字元串是常量:它們的值在建立之後不能更改

字元串的底層是一個被final修飾的數組,不能改變,是一個常量

private final byte[] value;

由于String類的對象内容不可改變,是以每當進行字元串拼接時,總是會在記憶體中建立一個新的對象。列如:

package com.byxx.yunan.test.string;

/**
 * @Author yww
 * @CreateTime 2021-02-10
 */
public class Test2 {
    public static void main(String[] args) {
        String str = "a"+"b"+"c";
        // "a", "b", "c"  3個字元串
        // "a" + "b"  "ab" 一個字元串
        // "ab" + "c" 一個字元串
    }
}
           

StringBuilder類

字元串緩沖區,可以提高字元串的操作效率 (看成一個長度可以變化的字元串) 底層也是一個數組,但沒有被final修飾,可以改變長度。

byte[] value = new byte[16];

“a” + “b” + “c” = “abc”;

StringBuilder 在記憶體中始終是一個數組,占用空間少,效率高,如果超出了StringBuilder的容量,會自動的擴容。

Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO
package com.byxx.yunan.test.string;

/**
 * @Author yww
 * @CreateTime 2021-02-10
 */
public class Test3 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        StringBuilder sb2 = sb.append("a");
        System.out.println(sb == sb2);// == 比較的記憶體位址(兩個對象是同一個對象)  是以 sb == sb2 輸出結果為true

        //StringBuilder 鍊式寫法
        sb.append(1).append("2").append('3').append(4.0);
        System.out.println(sb); // a1234.0

        //reverse(); 反轉
        sb.reverse();
        System.out.println(sb);// 0.4321a
    }
}
           

循環

for 循環

//for i
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
           

增強 for 循環

//增強for
for (String s : list) {
    System.out.println(s);
}
           

Iterator 疊代器

  • boolean hasNext(); 如果仍有元素可以疊代,則傳回true,判斷集合中還有沒有下一個元素,有就傳回true,沒有就傳回false
  • E next(); 傳回疊代的下一個元素
疊代器的使用步驟
  1. 使用集合的方法iterator() 擷取疊代器的實作類對象,使用Iterator接口接收(多态)
  2. 使用Iterator接口中的方法hasNext判斷還有沒有下一個元素
  3. 使用Iterator接口中的方法next取出集合中的下一個元素
package com.byxx.yunan.test.string;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * @Author yww
 * @CreateTime 2021-02-12
 */
public class Test4 {
    public static void main(String[] args) {
        Collection<String> lists = new ArrayList<>();
        lists.add("張三");
        lists.add("李四");
        lists.add("王五");
        lists.add("劉六");
        lists.add("陳七");

        //使用iterator疊代器 疊代
        Iterator<String> iterator = lists.iterator();
        //hasNext()判斷還有沒有下一個元素
        while(iterator.hasNext()){
            //iterator.next() 取出集合中的下一個元素
            System.out.println(iterator.next());
        }

    }
}
           

集合

Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

Collection頂級集合接口

  • boolean add (E e); 向集合中添加元素
  • boolean remove (E e); 删除集合中的某個元素
  • void clear (); 清空集合中所有的元素
  • boolean contains (E e); 判斷集合中是否包含某個元素
  • boolean isEmpty (); 判斷集合是否為空
  • int size (); 擷取集合的長度
  • Object[] toArray (); 将集合轉成一個數組

List

  • List接口特點:
    1. 有序的集合,存儲元素和取出元素的順序是一緻的(存儲123,取出123)
    2. 有索引,包含了一些帶索引的方法
    3. 允許存儲重複的元素
  • List接口中帶索引的方法(特有)
    • public void add(int index,E element); 将指定的元素,添加到該集合的指定位置上
    • public E get(int index); 傳回集合中指定位置的元素
    • public E remove(int index); 移出清單中指定位置的元素,傳回的是被移出的元素
    • public E set(int index,E element); 用指定元素替換集合中指定位置的元素,傳回值傳回更新前的元素
package com.byxx.yunan.test.arrays;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * List接口特點:
 *   1. 有序的集合,存儲元素和取出元素的順序是一緻的(存儲123,取出123)
 *   2. 有索引,包含了一些帶索引的方法
 *   3. 允許存儲重複的元素
 * List接口中帶索引的方法(特有)
 *   - public void add(int index,E element); 将指定的元素,添加到該集合的指定位置上
 *   - public E get(int index); 傳回集合中指定位置的元素
 *   - public E remove(int index); 移出清單中指定位置的元素,傳回的是被移出的元素
 *   - public E set(int index,E element); 用指定元素替換集合中指定位置的元素,傳回值傳回更新前的元素
 */
public class Test9 {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        //使用add方法往集合中添加元素
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");
        //列印list,沒有輸出記憶體位址,代表了内部重寫了toString()方法
        System.out.println(list);//[a,b,c,d,a]

        //public void add(int index,E element); 将指定的元素,添加到該集合的指定位置上
        list.add(2,"DDDDD");
        System.out.println(list);//[a, b, DDDDD, c, d, a]

        //public E remove(int index); 移出清單中指定位置的元素,傳回的是被移出的元素
        String removeStr = list.remove(2);
        System.out.println(removeStr);//DDDDD

        //public E set(int index,E element); 用指定元素替換集合中指定位置的元素,傳回值傳回更新前的元素
        list.set(0,"A");
        System.out.println(list);//[A,b,c,d,a]

        //public E get(int index); 傳回集合中指定位置的元素

        //for i
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        //增強for
        for (String s : list) {
            System.out.println(s);
        }

        //iterator疊代器
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }

    }
}

           

ArrayList

ArrayList集合資料存儲的結構是數組結構,元素增删慢,查找快,線程不安全,由于日常開發中使用最多的功能為查詢資料,周遊資料,是以ArrayList是最常用的集合。

LinkedList

LinkedList集合資料存儲的結構是雙向連結清單,元素增删快,查找快,線程不安全。

package com.byxx.yunan.test.arrays;

import java.util.LinkedList;

/**
 * java.util.LinkedList集合 implements List接口
 * LinkedList集合的特點:
 *      1.底層是一個連結清單結構:查詢慢,增删快
 *      2.裡面包含了大量操作首尾元素的方法
 *      注意:使用LinkedList集合特有的方法,不能使用多态
 *      
 *      - public void addFirst(E e); 将指定元素插入此清單的開頭
 *      - public void addLast(E e); 将指定元素添加到此清單的結尾
 *      - public void push(E e); 将元素推入此清單所表示的堆棧 push()方法等同于addFirst()方法
 *
 *      - public E getFirst(); 傳回此清單的第一個元素
 *      - public E getLast(); 傳回此清單的最後一個元素
 *
 *      - public E removeFirst(); 移出并傳回此清單的第一個元素
 *      - public E removeLast(); 移出并傳回此清單的最後一個元素
 *      - public E pop(); 從此清單所表示的堆棧處彈出一個元素 pop()方法等同于removeFirst()方法
 *
 *      - public boolean isEmpty(); 如果清單不包含元素,則傳回true
 */
public class Test10 {
    public static void main(String[] args) {
        LinkedList<String> linked = new LinkedList<>();
        linked.add("aaa");
        linked.add("bbb");
        /*
            - public void addFirst(E e); 将指定元素插入此清單的開頭
            - public void addLast(E e); 将指定元素添加到此清單的結尾
            - public void push(E e); 将元素推入此清單所表示的堆棧 push()方法等同于addFirst()方法
         */
        linked.addFirst("www");
        linked.addLast("com");
        linked.push("YYYYYY");

        System.out.println(linked);//[YYYYYY, www, aaa, bbb, com]

        /*
            - public E getFirst(); 傳回此清單的第一個元素
            - public E getLast(); 傳回此清單的最後一個元素

         */
        String first = linked.getFirst();
        String last = linked.getLast();

        System.out.println("第一個元素:"+first+" 最後一個元素:"+last);
        System.out.println(linked);

        /*
            - public E removeFirst(); 移出并傳回此清單的第一個元素
            - public E removeLast(); 移出并傳回此清單的最後一個元素
            - public E pop(); 從此清單所表示的堆棧處彈出一個元素 等同于removeFirst()方法
         */
        String pop = linked.pop();

        linked.clear();//清空集合中的元素 在擷取集合中的元素會抛出NoSuchElementException


    }
}
           

Set

Set接口和List接口一樣,同樣繼承Collection接口,它與Collection接口中的方法基本一緻,并沒有對Collection接口進行功能上的擴充,隻是比Collection接口更加嚴格了。與List接口不同的是,Set接口中元素無序,并且都會以某種規則保證存入的元素不出現重複。

Set集合中有多個子類,比如:HashSet,TreeSet這兩個集合。

Set集合取出元素的方式可以采用:疊代器,增強for

HashSet

HashSet是Set接口的一個實作類,它所存儲的元素是不可重複的,并且元素都是無序的(即存取順序不一緻)。HashSet底層實作其實是一個HashMap支援。

HashSet是根據對象的哈希值來确定元素在集合中的存儲位置,是以具有良好的存取和查找性能。保證元素唯一性的方式依賴于:hashCode和equals方法。

package com.byxx.yunan.test.arrays;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * Set接口 extends Collection接口
 * Set接口的特點:
 *      1.不允許存儲重複的元素
 *      2.沒有索引,沒有帶索引的方法,也不能使用普通的for循環周遊
 * HashSet特點:
 *      1.不允許存儲重複的元素
 *      2.沒有索引,沒有帶索引的方法,也不能使用普通的for循環周遊
 *      3.是一個無序的集合,存儲元素和取出元素的順序有可能不一緻
 *      4.底層是一個哈希表結構(查詢速度非常的快)
 */
public class Test11 {
    public static void main(String[] args) {
        Set<Integer> hashSet = new HashSet<>();

        hashSet.add(1);
        hashSet.add(3);
        hashSet.add(2);
        hashSet.add(1);

        //疊代器 循環
        Iterator<Integer> iterator = hashSet.iterator();
        while(iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);//輸出123
        }

        //增強for 循環
        for (Integer iter : hashSet) {
            System.out.println(iter);//輸出123
        }
    }
}
           

哈希值

哈希值:是一個十進制的整數,由系統随機給出(就是對象的位址,是一個邏輯位址,是模拟出來得到的位址,不是資料實際存儲的實體位址)。

package com.byxx.yunan.test.collection;

import lombok.ToString;

/**
 * 哈希值:是一個十進制的整數,由系統随機給出(就是對象的位址,是一個邏輯位址,是模拟出來得到的位址,不是資料實際存儲的實體位址)
 * 在Object類由一個方法,可以擷取對象的哈希值
 * int hashCode(); 傳回該對象的哈希碼值
 * hashCode 源碼:
 *      public native int hashCode():
 *      native:代表該方法調用的是本地作業系統的方法
 */
public class Test1 {
    public static void main(String[] args) {
        //User類繼承了Object類,是以可以使用Object類的hashCode方法
        User u1 = new User();
        int code1 = u1.hashCode();
        System.out.println(code1);//521645586

        User u2 = new User();
        int code2 = u2.hashCode();
        System.out.println(code2);//1296064247
        u2.toString();

        /*
            toString()方法源碼:
                return getClass().getName() + "@" + Integer.toHexString(hashCode());
         */
        System.out.println(u1);//[email protected]
        System.out.println(u2);//[email protected]
        System.out.println(u1 == u2);//false

    }
}
           

HashSet集合存儲資料的結構 (哈希表)

在jdk1.8之前,哈希表底層采用數組+連結清單實作,即使用連結清單處理沖突,同一個hash值的連結清單都存儲在一個連結清單裡。但是當一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。而在jdk1.8中,哈希表存儲采用數組+連結清單+紅黑樹實作,數組初始長度為16,當連結清單長度超過門檻值(8)時,将連結清單轉換為紅黑樹,這樣大大減少了查找實際。

Set集合存儲元素不重複的原理

Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

HashSet存儲自定義類型元素

  • 存儲元素(String,Integer,…Person),必須重寫hashCode和equals方法
package com.byxx.yunan.test.collection;

import java.util.HashSet;
import java.util.Objects;

/**
 * HashSet存儲自定義類型元素
 *
 * set集合儲存元素唯一
 *  存儲的元素(String,Integer,...Person),必須重寫hashCode方法和equals方法
 *
 * 要求:
 *   同名同年齡的人,視為同一個人,隻能存儲一次
 */
public class Test3 {
    public static void main(String[] args) {
        Person p1 = new Person("張三",18);
        Person p2 = new Person("張三", 18);
        Person P3 = new Person("張三", 19);

        HashSet<Person> set = new HashSet<>();
        set.add(p1);
        set.add(p2);
        set.add(P3);
        //存儲類型沒有重寫hashCode和equals方法時
        System.out.println(p1==p2);//對比記憶體位址: false
        System.out.println(p1.equals(p2));//對比值: false
        System.out.println(set);//[Person{name='張三', age=18}, Person{name='張三', age=19}, Person{name='張三', age=18}]

        //對象重寫hashCode和equals方法後(完成需求,同名同年齡人,隻能存儲一次)
        System.out.println(p1==p2);//對比記憶體位址: false
        System.out.println(p1.equals(p2));//對比值: true
        System.out.println(set);//[Person{name='張三', age=18}, Person{name='張三', age=19}]
    }

}

//person類
class Person{
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name) &&
                Objects.equals(age, person.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
           

LinkedHashSet

  • LinkedHashSet集合 extends HashSet集合
  • 底層是一個哈希表 + 連結清單 (記錄元素的存儲順序),保證元素有序
package com.byxx.yunan.test.collection;

import java.util.HashSet;
import java.util.LinkedHashSet;

/**
 * @Author yww
 * @CreateTime 2021-02-21
 */
public class Test4 {
    public static void main(String[] args) {
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("www");
        hashSet.add("ccc");
        hashSet.add("bbb");
        System.out.println(hashSet);//[ccc, bbb, www]

        /*
            LinkedHashSet集合 extend HashSet集合
            特點:
                底層是一個哈希表 + 雙向連結清單 (多了一條連結清單是為了 記錄元素的存儲順序),保證存儲元素有序
         */
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("www");
        linkedHashSet.add("ccc");
        linkedHashSet.add("bbb");
        System.out.println(linkedHashSet);//[www, ccc, bbb]
    }
}
           

Collections工具類

  • Collections 是集合工具類,用來對集合進行操作,部分方法如下:
  • public static boolean addAll(Collection c,T… elements); 往集合中添加一些元素
  • public static void shuffle(List<?> list); 打亂集合順序
  • public static void sort(List list); 将集合中元素按照預設規則排序
  • public static void sort(List list,Comparator<? super T> ); 将集合中元素按照指定規則排序,被排序的集合裡存儲的元素,重寫Comparator接口中的方法compare定義排序的規則
package com.byxx.yunan.test.collection;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * @Author yww
 * @CreateTime 2021-02-22
 */
public class Test5 {
    public static void main(String[] args) {
        /*
          Collections工具類:
            public static <T> boolean addAll(Collection<T> c,T... elements); 往集合中添加一些元素
         */
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"1","2","3","4","5");
        System.out.println(list);//[1, 2, 3, 4, 5]

        //public static void shuffle(List<?> list);打亂集合順序,每次順序都不一緻
        Collections.shuffle(list);
        System.out.println(list);//[2, 3, 4, 5, 1]

        //public static <T> void sort(List<T> list); 将集合中元素按照預設規則排序
        Collections.sort(list);
        System.out.println(list);//[1, 2, 3, 4, 5]

        /*
          按年齡大小排序
          sort(List<T> list)使用前提
          被排序的集合裡存儲的元素,必須實作Comparable,重寫接口中的compareTo定義排序的規則
         */
        ArrayList<Role> roleList = new ArrayList<>();
        roleList.add(new Role("張三",17));
        roleList.add(new Role("李四",19));
        roleList.add(new Role("王五",20));

        /*
           public static <T> void sort(List<T> list,Comparator<? super T> );
           将集合中元素按照指定規則排序,被排序的集合裡存儲的元素,重寫Comparator接口中的方法compare定義排序的規則 	
         */
        //升序 o1.getAge().compareTo(o2.getAge())
        Collections.sort(roleList, new Comparator<Role>() {
            @Override
            public int compare(Role o1, Role o2) {
                return o1.getAge().compareTo(o2.getAge());
            }
        });
        System.out.println(roleList);//[Role{name='張三', age=17}, Role{name='李四', age=19}, Role{name='王五', age=20}]

        //降序 o2.getAge().compareTo(o1.getAge())
        Collections.sort(roleList, new Comparator<Role>() {
            @Override
            public int compare(Role o1, Role o2) {
                return o2.getAge().compareTo(o1.getAge());
            }
        });
        System.out.println(roleList);//[Role{name='王五', age=20}, Role{name='李四', age=19}, Role{name='張三', age=17}]
    }
}

//角色類
class Role{
    private String name;
    private Integer age;
    
    public Role() {
    }
    
	public Role(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Role{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
    
}
           

Map

  • Map集合的特點:
    1. Map集合是一個雙列集合,一個元素包含兩個值 (一個key,一個value)
    2. Map集合中的元素,key和value的資料類型可以相同,也可以不同
    3. Map集合中的元素,key是不允許重複的,value是可以重複的 (如果出現key重複,後put重複的value值會替換之前put的value)
    4. Map集合中的元素,key和value是一 一對應的
  • Map接口常用方法
    1. public V put(K key,V value); 把指定的鍵與指定的值添加到Map集合中
    2. public V remove(Object key); 把指定的鍵所對應的鍵值對元素在Map集合中删除,傳回被删除元素的值
    3. public V get(Object key); 根據指定的鍵,在Map集合中擷取對應的值
    4. boolean containsKey(Object key); 判斷集合中是否包含指定的鍵
    5. public Set keySet(); 擷取Map集合中所有的鍵,存儲到Set集合中
    6. public Set<Map.Entry<K,V>> entrySet(); 擷取到Map集合中所有的鍵值對對象的集合(Set集合)
package com.byxx.yunan.test.collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Author yww
 * @CreateTime 2021-02-24
 */
public class Test6 {
    public static void main(String[] args) {
        HashMap<String, Object> map = new HashMap<>();
        //public V put(K key,V value) 添加元素到集合
        map.put("name", "張三");
        map.put("sex", "男");
        map.put("age", 20);
        System.out.println(map);//{sex=男, name=張三, age=20}

        //public V remove(Object key) 删除集合中指定的key
        map.remove("age");
        System.out.println(map);//{sex=男, name=張三}

        //public V get(Object key) 根據指定的值,擷取對應的值
        Object name = map.get("name");
        System.out.println(name);//張三

        //public Set<K> keySet() 擷取Map集合中所有的鍵,存儲到Set集合中
        Set<String> keySet = map.keySet();
        //for增強
        for (String key : keySet) {
            Object value = map.get(key);
            System.out.print(value);//男 張三
        }
        //疊代器
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            Object value = map.get(key);
            System.out.print(value);//男 張三
        }

        //public Set<Map.Entry<K,V>> entrySet(); 擷取map集合中的 鍵值對 對象
        Set<Map.Entry<String, Object>> entrySet = map.entrySet();
        //for增強
        for (Map.Entry<String, Object> entry : entrySet) {
            String key = entry.getKey();
            Object value = entry.getValue();
            /*
                key:sex  value:男
                key:name  value:張三
             */
            System.out.println("key:" + key + "  value:" + value);
        }

        //疊代器
        Iterator<Map.Entry<String, Object>> entryIterator = map.entrySet().iterator();
        while (entryIterator.hasNext()) {
            Map.Entry<String, Object> entryMap = entryIterator.next();
            String key = entryMap.getKey();
            Object value = entryMap.getValue();
            /*
                key:sex  value:男
                key:name  value:張三
             */
            System.out.println("key:" + key + "  value:" + value);
        }

    }
}
           

HashMap

  • HashMap集合 implements Map接口
  • HashMap集合特點:
    1. HashMap集合底層是哈希表,查詢效率快

      ​ JDK1.8之前:數組 + 連結清單

      ​ JDK1.8之後:數組 + 連結清單 + 紅黑樹

    2. HashMap集合是一個無序的集合,存儲元素和取出元素的順序有可能不一緻
  • HashMap存儲自定義類型鍵值
    1. Map集合保證key是唯一的
    2. 作為key的元素,必須重寫hashCode方法和equals方法,以保證key唯一
package com.byxx.yunan.test.collection;

import com.sun.org.apache.bcel.internal.generic.NEW;
import org.aspectj.weaver.ast.Or;

import java.util.HashMap;
import java.util.Objects;

/**
 * HashMap集合 implements Map接口
 */
public class Test7 {
    public static void main(String[] args) {
        /*
          hashMap存儲自定義類型
            Map集合保證key是唯一的:
                作為key的元素,必須重寫hashCode方法和equals方法,以保證key唯一
         */
        HashMap<Organ, Object> hashMap = new HashMap<>();
        //Organ對象沒有重寫hashCode和equals時,同值對象作為key是不會去重的
        hashMap.put(new Organ("張三","19"),20);
        hashMap.put(new Organ("李四","20"),31);
        hashMap.put(new Organ("張三","19"),23);
        System.out.println(hashMap);//{Organ{name='張三', age='19'}=20, Organ{name='張三', age='19'}=23, Organ{name='李四', age='20'}=31}

        //Organ對象重寫hashCode和equals後,同值對象作為key會去重
        HashMap<Organ, Object> organMap = new HashMap<>();
        organMap.put(new Organ("張三","19"),20);
        organMap.put(new Organ("李四","20"),31);
        organMap.put(new Organ("張三","19"),23);
        System.out.println(organMap);//{Organ{name='李四', age='20'}=31, Organ{name='張三', age='19'}=23}
    }

}

//Organ類
class Organ{
    private String name;
    private String age;

    public Organ() {
    }

    public Organ(String name, String age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Organ organ = (Organ) o;
        return Objects.equals(name, organ.name) &&
                Objects.equals(age, organ.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Organ{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
           

LinkedHashMap

  • LinkedHashMap集合 extends HashMap集合
  • LikedHashMap集合的特點:
    1. LinkedHashMap集合底層是哈希表 + 連結清單 (保證疊代的順序)
    2. LinkedHashMap集合是一個有序的集合,存儲元素和取出元素的順序是一緻的
package com.byxx.yunan.test.collection;

import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * LinkedHashMap<K,V> extends HashMap<K,V>
 * 底層結構:
 *      哈希表 + 連結清單 (記錄元素的順序)
 */
public class Test8 {
    public static void main(String[] args) {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("a","D");
        hashMap.put("c","C");
        hashMap.put("b","B");
        hashMap.put("a","A");
        System.out.println(hashMap);// key不允許重寫,無序 {a=A, b=B, c=C}

        LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("a","D");
        linkedHashMap.put("c","C");
        linkedHashMap.put("b","B");
        linkedHashMap.put("a","A");
        System.out.println(linkedHashMap);// key不允許重寫,有序 {a=A, c=C, b=B}
    }
}
           

TreeMap

  • TreeMap<K,V> extends AbstractMap<K,V>
  • TreeMap特點:
    1. key唯一,按照自然順序排序
package com.byxx.yunan.test.collection;

import org.apache.commons.collections4.map.LinkedMap;

import java.util.*;

/**
 * @Author yww
 * @CreateTime 2021-02-24
 */
public class Test9 {
    public static void main(String[] args) {
        TreeMap<Object, Object> treeMap1 = new TreeMap<>();
        //TreeMap按照自然順序疊代
        treeMap1.put(1,"aaa");
        treeMap1.put(3,"ccc");
        treeMap1.put(2,"bbb");
        System.out.println(treeMap1);//{1=aaa, 2=bbb, 3=ccc}

        TreeMap<String, Object> treeMap2 = new TreeMap<>();
        treeMap2.put("a","AAA");
        treeMap2.put("c","CCC");
        treeMap2.put("b","BBB");
        System.out.println(treeMap2);//{a=AAA, b=BBB, c=CCC}

    }
}
           

HashTable

  • HashTable<K,V> 集合 implements Map<K,V> 集合
  • HashTable 與 HashMap差別
    1. HashTable 底層是一個哈希表,是一個線程安全的集合,是單線程集合,速度慢

      HashMap 底層是一個哈希表,是一個線程不安全的集合,是多線程的集合,速度快

    2. HashTable 不能存儲 null 鍵 null 值

      HashMap(包括其他集合) 可以存儲 null 鍵 null 值

    3. HashTable 和 vector 集合一樣,在jdk1.2版本之後被更先進的集合(HashMap,ArrayList)取代了
    package com.byxx.yunan.test.collection;
    
    import java.util.HashMap;
    import java.util.Hashtable;
    
    /**
     * @Author yww
     * @CreateTime 2021-02-24
     */
    public class Test10 {
        public static void main(String[] args) {
            /*
               HashT ,able<K,V>集合 implements Map<K,V>集合
    
               HashTable: 底層是一個哈希表,是一個線程安全的集合,是單線程集合,速度慢
               HashMap: 底層是一個哈希表,是一個線程不安全的集合,是多線程的集合,速度快
    
               HashTable: 不能存儲null鍵null值
               HashMap(包過其他集合): 可以存儲null鍵null值
    
               HashTable和vector集合一樣,在jdk1.2版本之後被更先進的集合(HashMap,ArrayList)取代了
             */
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put(null,"A");
            hashMap.put("B",null);
            hashMap.put(null,null);
            System.out.println(hashMap);//{null=null, B=null}
    
            Hashtable<String, Object> hashTable = new Hashtable<>();
            hashTable.put(null,"A");//報異常: NullPointerException
            hashTable.put("B",null);//報異常: NullPointerException
            hashTable.put(null,null);//報異常: NullPointerException
    
        }
    }
               

資料結構

常見的資料結構

資料存儲的常用結構有:棧,隊列,數組,連結清單,紅黑樹。

  • 棧 :stack,又稱堆棧,它是運算受限的線性表,其限制是僅允許在标的一端進行插入和删除操作,不允許在其他任何位置進行添加,查找,删除等操作。

簡單的來說:采用該結構的集合,對元素的存取有如下的特點

  • 先進後出(即,存進去的元素,要在它後面的元素依次取出後,才能取出該元素)。例如,子彈壓進彈夾,先壓進去的子彈在下面,後壓進去的子彈在上面,當開槍時,先彈出上面的子彈,然後才能彈出下面的子彈。
  • 棧的入口,出口都是棧的頂端位置。
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

隊列

  • 隊列:queue,簡稱隊,它同堆棧一樣,也是一種運算受限的線性表,其限制是僅允許在表的一端進行插入,而在表的另一端進行删除。

簡單的說,采用該結構的集合,對元素的存取有如下的特點:

  • 先進先出(即,存進去的元素,要在它前面的元素依次取出來後,才能取出該元素)。例如,小火車過山洞,車頭先進去,車尾後進去;車頭先出來,車尾後出來。
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

數組

  • 數組:Array,是有序的元素序列,數組是在記憶體中開辟一段連續的空間,并在此空間放元素,就像是一排出租屋,有100個房間,從001到100每個房間都有固定編号,通過編号就可以快速找到租房子的人。

簡單的說,采用該結構的集合,對元素的存取有如下的特點:

  • 查找元素快:通過索引,可以快速通路指定位置的元素。
  • 增删元素慢
    • 指定索引位置增加元素,需要建立一個新數組,将指定新元素存儲在指定索引位置,再把原數組元素根據索引,複制到新數組對應索引的位置。
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

連結清單

  • 連結清單:linked list,由一系列節點node(連結清單中每一個元素稱為節點)組成,節點可以在運作時動态生成。每個節點包括兩個部分:一個是存儲資料元素的資料域,另一個是存儲下一個節點位址的指針域,連結清單結構有單向連結清單與雙向連結清單
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

File

概述

File 類是檔案和目錄路徑名的抽象表示,主要用于檔案和目錄的建立,查找和删除等操作。

File類中靜态成員變量

  • static String pathSeparator 與系統有關的路徑分隔符 //windows: 分号; linux: 冒号:
  • static char pathSeparatorChar 與系統有關的路徑分隔符
  • static String separator 與系統有關的預設名稱分割符 //windows: 反斜杆\ linux: 正斜杆/
  • static String separatorChar 與系統有關的預設名稱分隔符
package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-24
 */
public class Test1 {
    public static void main(String[] args) {
        /*
            路徑分隔符pathSeparator 與 pathSeparatorChar 一緻,内部就是将Char變成了字元串
            public static final String pathSeparator = "" + pathSeparatorChar;
         */
        String pathSeparator = File.pathSeparator;
        System.out.println(pathSeparator);//windows: 分号;  linux:冒号:

        /*
           檔案名稱分隔符separator 與 separatorChar 一緻,内部就是将Char變成了字元串
           public static final String separator = "" + separatorChar;
         */
        String separator = File.separator;
        System.out.println(separator);//windows: 反斜杆\  linux: 正斜杆/
    }
}
           

File類構造方法

  • File (String pathname) 通過将給定路徑名稱字元串轉換為抽象路徑名來建立一個新 File 執行個體
  • File (String parent,String child) 根據 parent 路徑名字元串和 child 路徑名字元串建立一個新 File 執行個體
  • File (File parent,String child) 根據 parent 抽象路徑名和 child 路徑名字元串建立一個新 File 執行個體
package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test2 {
    public static void main(String[] args) {
        /*
           File(String pathname)
           通過将給定路徑名稱字元串轉換為抽象路徑名來建立一個新 File 執行個體
         */
        File file1 = new File("D://a.txt");
        System.out.println(file1);//D:\a.txt

        /*
           File(String parent,String child)
           根據 parent 路徑名字元串和 child 路徑名字元串建立一個新 File 執行個體
         */
        File file2 = new File("D://","a.txt");
        System.out.println(file2);//D:\a.txt

        /*
           File(File parent,String child)
           根據 parent 抽象路徑名和 child 路徑名字元串建立一個新 File 執行個體
         */
        File parentFile = new File("E://");
        File file3 = new File(parentFile,"a.txt");
        System.out.println(file3);//E:\a.txt

    }
}
           

File類常用方法

擷取功能的方法

  • public String getAbsolutePath() 傳回此File的絕對路徑名 字元串
  • public String getPath() 将此File轉換為路徑名 字元串
  • public String getName() 傳回由此File表示的檔案或目錄的名稱
  • public long length() 傳回由此File表示的檔案的長度
package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test3 {
    public static void main(String[] args) {
        getAbsolutePath();
        getPath();
        getName();
        length();
    }

    /**
     * public String getAbsolutePath()  傳回此File的絕對路徑名 字元串
     * 擷取的構造方法中的路徑無論路徑是絕對的還是相對的,getAbsolutePath()方法傳回的都是絕對路徑
     */
    public static void getAbsolutePath(){
        File file1 = new File("D:\\log\\a.txt");
        String absolutePath1 = file1.getAbsolutePath();
        System.out.println(absolutePath1);// D:\log\a.txt

        //如果直接填寫檔案,則按目前項目路徑作為參照物 擷取絕對路徑
        File file2 = new File("c.txt");
        String absolutePath2 = file2.getAbsolutePath();
        System.out.println(absolutePath2);// F:\WorkSpaces\IdeaWork\yunan\c.txt
    }


    /**
     * public String getPath() 将此File轉換為路徑名 字元串
     * 擷取的構造方法中傳遞的路徑
     */
    public static void getPath(){
        File file1 = new File("D:\\log\\a.txt");
        String path1 = file1.getPath();
        System.out.println(path1);// D:\log\a.txt

        File file2 = new File("a.txt");
        String path2 = file2.getPath();
        System.out.println(path2);// a.txt
    }

    /**
     * public String getName() 擷取File結尾的檔案名稱
     */
    public static void getName(){
        File file1 = new File("D:\\log");
        String name1 = file1.getName();
        System.out.println(name1);//log

        File file2 = new File("a.txt");
        String name2 = file2.getName();
        System.out.println(name2);//a.txt
    }

    /**
     * public long length() 傳回由此File表示的檔案的長度
     * 擷取的是構造方法指定檔案的大小,以位元組為機關
     * 注意:
     *    檔案夾或者 給File構造方法中的路徑不存在,length 傳回0
     */
    public static void length(){
        File file1 = new File("D:\\log\\a.txt");
        long length = file1.length();
        System.out.println(length);//858
    }

}
           

判斷功能的方法

  • public boolean exists() 判斷檔案是否存在,存在傳回 true, 不存在傳回 false
  • public boolean isDirectory() 判斷是否為目錄(檔案夾),目錄(檔案夾) 傳回 true, 其他傳回 false
  • public boolean isFile() 判斷是否為檔案,是檔案 傳回 true,非檔案 傳回 false
package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test4 {
    public static void main(String[] args) {
        exists();
        isDirectory();
        isFile();
    }

    /**
     * public boolean exists() 判斷檔案是否存在
     * 存在傳回 true, 不存在傳回 false
     */
    public static void exists(){
        File file1 = new File("D:\\log\\a.txt");
        boolean exists1 = file1.exists();
        System.out.println(exists1);//true

        File file2 = new File("D:\\log");
        boolean exists2 = file2.exists();
        System.out.println(exists2);//true
    }

    /**
     * public boolean isDirectory() 判斷是否為目錄(檔案夾)
     * 目錄(檔案夾) 傳回 true, 其他傳回 false
     */
    public static void isDirectory(){
        File file1 = new File("D:\\log\\a.txt");
        boolean directory1 = file1.isDirectory();
        System.out.println(directory1);//false

        File file2 = new File("D:\\log");
        boolean directory2 = file2.isDirectory();
        System.out.println(directory2);//true
    }

    /**
     * public boolean isFile() 判斷是否為檔案
     * 是檔案 傳回 true,非檔案 傳回 false
     */
    public static void isFile(){
        File file1 = new File("D:\\log\\a.txt");
        boolean directory1 = file1.isFile();
        System.out.println(directory1);//true

        File file2 = new File("D:\\log");
        boolean directory2 = file2.isFile();
        System.out.println(directory2);//false
    }

}
           

建立删除功能的方法

  • public boolean createNewFile() 建立一個空的新檔案,檔案不存在,建立檔案成功傳回 true,檔案存在傳回 false
  • public boolean delete() 删除檔案(檔案,檔案夾都可以),删除成功 傳回 true,删除失敗 傳回 false
  • public boolean mkdir() 建立單層檔案夾,不可建立多層,建立成功傳回 true,檔案已存在,建立失敗傳回 false
  • public boolean mkdirs() 建立檔案夾,可以建立單層,也可以建立多層檔案夾,建立成功傳回 true,檔案已存在,建立失敗傳回 false
package com.byxx.yunan.test.io;

import java.io.File;
import java.io.IOException;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test5 {
    public static void main(String[] args) throws IOException {
        createNewFile();
        delete();
        mkdir();
        mkdirs();
    }

    /**
     * public boolean createNewFile() 建立一個空的新檔案
     * 檔案不存在,建立檔案成功傳回 true
     * 檔案存在傳回 false
     * @throws IOException
     */
    public static void createNewFile() throws IOException {
        File file1 = new File("D:\\log\\a.txt");//本地有此檔案
        boolean newFile1 = file1.createNewFile();
        System.out.println(newFile1);//false

        File file2 = new File("D:\\log\\ccc.txt");//本地無此檔案
        boolean newFile2 = file2.createNewFile();
        System.out.println(newFile2);//true
    }

    /**
     * public boolean delete() 删除檔案(檔案,檔案夾都可以)
     * 删除成功 傳回 true
     * 删除失敗 傳回 false
     */
    public static void delete(){
        File file1 = new File("D:\\log\\ccc.txt");//本地存在
        boolean delete1 = file1.delete();
        System.out.println(delete1);//true

        File file2 = new File("D:\\log\\ccc.txt");//delete()删除後,不存在,傳回false
        boolean delete2 = file1.delete();
        System.out.println(delete2);//false

        File file3 = new File("D:\\aaaaa");//檔案夾
        boolean delete3 = file3.delete();
        System.out.println(delete3);//true
    }

    /**
     * public boolean mkdir() 建立單層檔案夾,不可建立多層
     * 建立成功傳回 true
     * 檔案夾存在,建立失敗傳回 false
     */
    public static void mkdir(){
        File file1 = new File("D:\\log\\第一個檔案夾");//建立單層
        boolean mkdir1 = file1.mkdir();
        System.out.println(mkdir1);//true

        File file2 = new File("D:\\log\\第一個檔案夾");//建立單層
        boolean mkdir2 = file2.mkdir();
        System.out.println(mkdir2);//false

        File file3 = new File("D:\\log\\第一層檔案夾\\第二層檔案夾");//建立多層
        boolean mkdir3 = file3.mkdir();
        System.out.println(mkdir3);//false

    }

    /**
     * public boolean mkdirs() 建立檔案夾,可以建立單層,也可以建立多層檔案夾
     * 建立成功傳回 true
     * 檔案夾存在,建立失敗傳回 false
     */
    public static void mkdirs(){
        File file1 = new File("D:\\log\\第一層檔案夾");//單層檔案夾
        boolean mkdirs1 = file1.mkdirs();
        System.out.println(mkdirs1);//true

        File file2 = new File("D:\\log\\第一次檔案夾\\第二層檔案夾\\第三層檔案夾\\第四層檔案夾");//多層檔案夾
        boolean mkdirs2 = file2.mkdirs();
        System.out.println(mkdirs2);//true
    }

}
           

目錄的周遊

  • public String[] list() 傳回一個String 數組,擷取 File 目錄下所有檔案及檔案夾(不包括子子檔案或檔案夾),擷取為檔案或檔案夾名稱
  • public File[] listFiles() 傳回一個File數組,擷取 File 目錄下所有檔案及檔案夾(不包括子子檔案或檔案夾),擷取為檔案對象,可以擷取更多資訊
package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test6 {
    public static void main(String[] args) {
        list();
        listFiles();
    }

    /**
     * public String[] list() 擷取目錄下所有檔案及檔案夾(不包括子子檔案或檔案夾)
     * 擷取為檔案或檔案夾名稱
     */
    public static void list(){
        File file = new File("D:\\這是一個目錄檔案夾");
        String[] list = file.list();
        for (String name : list) {
            /*
              輸出結果:
                  子檔案1.txt
                  子檔案夾1
                  子檔案夾2
             */
            System.out.println(name);
        }
    }

    /**
     * public File[] listFiles() 擷取目錄下所有檔案及檔案夾(不包括子子檔案或檔案夾)
     * 擷取為檔案對象,可以擷取更多資訊
     */
    public static void listFiles(){
        File file = new File("D:\\這是一個目錄檔案夾");
        File[] files = file.listFiles();
        for (File str : files) {
            /*
              輸出結果:
                  D:\這是一個目錄檔案夾\子檔案1.txt
                  D:\這是一個目錄檔案夾\子檔案夾1
                  D:\這是一個目錄檔案夾\子檔案夾2
             */
            System.out.println(str);
        }
    }
}
           

遞歸

執行個體:

package com.byxx.yunan.test.io;

import java.io.File;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test7 {
    public static void main(String[] args) {
        File file = new File("D:\\這是一個目錄檔案夾");
        getAllFile(file);
        /*
           輸出結果:
                D:\這是一個目錄檔案夾\子檔案1.txt
                D:\這是一個目錄檔案夾\子檔案夾1\子子檔案夾1-1\子子子檔案1-1-1.txt
                D:\這是一個目錄檔案夾\子檔案夾1\子子檔案夾1-1\子子子檔案夾1-1-1
                D:\這是一個目錄檔案夾\子檔案夾1\子子檔案夾1-1
                D:\這是一個目錄檔案夾\子檔案夾1
                D:\這是一個目錄檔案夾\子檔案夾2\子子類檔案夾2-1
                D:\這是一個目錄檔案夾\子檔案夾2
         */
    }

    /**
     * 擷取目錄下所有檔案,遞歸調用
     * @param file
     */
    public static void getAllFile(File file){
        File[] files = file.listFiles();
        for (File fileStr : files) {
            if(fileStr.isDirectory()){//如果是檔案夾,就遞歸調用自身
                getAllFile(fileStr);
            }
            System.out.println(fileStr);
        }
    }
}
           

IO

位元組流

位元組輸出流 OutputStream

OutputStream 抽象類是表示位元組輸出流的所有類的超類,将指定的位元組資訊寫道目的地,它定義了位元組輸出流的基本共性功能方法

  • public void close() 關閉此輸出流并釋放與此流相關聯的任何系統資源
  • public void flush() 重新整理此輸出流并強制任何緩沖的輸出位元組被寫出
  • public void write(byte[] b) 将b.length位元組從指定的位元組數組寫入此輸出流
  • public void write(byte[] b, int off, int len) 從指定的位元組數組寫入len位元組,從偏移量off開始輸出到此輸出流
  • public abstract void write(int b) 将指定的位元組輸出流

FileOutputStream類

  • FileOutputStream extends OutputStream
  • FileOutputStream 檔案位元組輸出流 (把記憶體中的資料寫入到硬碟的檔案中)
  • 構造方法
    1. FileOutputStream(String name) 建立一個向具有指定名稱的檔案中寫入資料的輸出檔案流
    2. FileOutputStream(String name, boolean append) 建立一個向具有指定 name 的檔案中寫入資料的檔案輸出流,是否開啟資料寫入追加
    3. FileOutputStream(File file) 建立一個向指定File對象表示的檔案中寫入資料的檔案輸出流
    4. FileOutputStream(File file, boolean append) 建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流,是否開啟資料寫入追加

    參數:寫入資料的目的

    ​ String name :目的地是一個檔案的路徑

    ​ File file :目的地是一個檔案

    構造方法的作用:

    1. 建立一個FileOutputStream對象
    2. 會根據構造方法中傳遞的檔案 / 檔案路徑,建立一個空的檔案
    3. 會把FileOutputStream對象指向建立好的路徑
package com.byxx.yunan.test.io;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test8 {
    public static void main(String[] args) throws IOException {
        /*
           FileOutputStream(String name)
               String name: 構造方法中傳遞寫入資料的目的地
         */
        //1.建立一個FileOutputStream對象,構造方法中傳遞寫入資料的目的地
        FileOutputStream fos1 = new FileOutputStream("D:\\log\\c.txt");
        //2.調用FileOutputStream對象中的方法write,把資料寫入到檔案中
        fos1.write("你好哇,HelloWorld".getBytes());
        //3.釋放資源(流使用會占用一定的記憶體,使用完畢要把記憶體清空,提供程式的效率)
        fos1.close();


        /*
           FileOutputStream(String name, boolean append)
               String name: 構造方法中傳遞寫入資料的目的地
               boolean append: 追加寫入開關
                       true: 建立對象不會覆寫原檔案,繼續在檔案的末尾追加寫入資料
                       false: 建立一個新檔案,覆寫原檔案
         */
        FileOutputStream fos2 = new FileOutputStream("D:\\log\\d.txt",true);//資料寫入目的地,開啟末尾追加寫入資料
        for (int i = 0; i < 5; i++) {
            String str = "序号"+(i+1);
            fos2.write(str.getBytes());//字元轉位元組數組寫入檔案中
            fos2.write("\r\n".getBytes());//  \r\n 換行寫入資料
        }
        fos2.close();

        /*
           d.txt中寫入結果為:
                序号1
                序号2
                序号3
                序号4
                序号5
         */

    }
}
           

位元組輸入流 InputStream

InputStream 抽象類是表示位元組輸入流的所有類的超類,可以讀取位元組資訊到記憶體中,它定義了位元組輸入流的基本共性功能方法

  • public void close() 關閉此輸入流并釋放與此流相關的任何系統資源
  • public abstract int read() 從輸入流讀取資料的下一個位元組
  • public int read(byte[] b) 從輸入流中讀取一些位元組數,并将他們存儲到位元組數組 b 中

FileInputStream類

  • FileInputStream extends InputStream
  • FileInputStream 檔案位元組輸出流 (從檔案中讀取位元組)
  • 構造方法
    1. FileInputStream(File file) 通過打開與實際檔案的連接配接建立一個FileInputStream,該檔案由檔案系統中的File對象 file命名
    2. FileInputStream(String name) 通過打開與實際檔案的連接配接來建立一個FileInputStream,該檔案由檔案系統中的路徑名 name 命名
      package com.byxx.yunan.test.io;
      
      import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator;
      
      import javax.print.DocFlavor;
      import java.io.FileInputStream;
      import java.io.IOException;
      
      /**
       * FileInputStream extends InputStream
       * FileInputStream 檔案位元組輸入流
       * 作用: 把硬碟檔案中的資料,讀取到記憶體中使用
       *
       * 構造方法:
       *      FileInputStream(String name)
       *      FileInputStream(File file)
       *      參數:讀取檔案的資料源
       *          String name: 檔案的路徑
       *          File file: 檔案
       *      構造方法的作用:
       *          1.會建立一個FileInputStream對象
       *          2.會把FileInputStream對象指定構造方法中要讀取的檔案
       *
       * 讀取資料的原理(硬碟-->記憶體)
       *      java程式 --> JVM --> OS作業系統 --> OS讀取資料的方法 --> 讀取檔案
       *
       * 位元組輸入流的使用步驟(重點):
       *      1.建立FileInputStream對象,構造方法中綁定要讀取的資料源
       *      2.使用FileInputStream對象中的方法read,讀取檔案
       *      3.釋放資源
       */
      public class Test {
          public static void main(String[] args) throws IOException {
              FileInputStream fis = new FileInputStream("D:\\log\\d.txt");
              /*
                public abstract int read()
                讀取檔案中的一個位元組并傳回,讀取到檔案的末尾傳回-1
                布爾表達式(len = fis.read()!=-1
                      1.fis.read() 讀取一個位元組
                      2.len = fis.read() 把讀取到的位元組指派給變量len
                      3.(len = fis.read())!=-1 判斷變量len是否不等于-1
              */
              int len = 0;
              while((len = fis.read())!=-1){
                  System.out.print((char)len);//abc
              }
              fis.close();//關閉流,釋放資源
      
              //============================read(byte[] byte)=================================
              /*
                public int read(byte b[]) 從輸出流中讀取一些位元組數,并将它們存儲到位元組數組 b 中
                使用byte[]數組作為緩沖區讀取
               */
              FileInputStream fis2 = new FileInputStream("D:\\log\\d.txt");
              byte[] bytes = new byte[1024];
              int len2 = 0;
              while((len2 = fis2.read(bytes))!=-1){
                  //因為byte[]初始化長度為1024,是以會輸出很多多餘空格
                  System.out.println(new String(bytes));//abcdefg     ....
                  /*
                     public String(byte bytes[], int offset, int length)
                     将位元組數組轉String,從哪開始到哪結束
                   */
                  System.out.println(new String(bytes,0,len2));//不會輸出多餘空格 abcdefg
              }
              //關閉資源
              fis2.close();
      
          }
      }
                 

複制檔案案例

package com.byxx.yunan.test.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @Author yww
 * @CreateTime 2021-02-25
 */
public class Test9 {
    public static void main(String[] args) throws IOException {
        /*
           實作檔案複制需求:
              1.使用輸入流FileInputStream讀取原檔案,轉成位元組數組
              2.使用輸出流FileOutputStream讀取擷取到的位元組數組
              3.使用輸出流FileOutputStream将資料寫入磁盤
         */
        File file = new File("D:\\log\\abc.jpg");
        if(file.exists()){//存在
            //輸入流,讀取檔案
            FileInputStream fis = new FileInputStream(file.getAbsolutePath());

            //輸出流,寫入檔案
            FileOutputStream fos = new FileOutputStream("F:\\abc.jpg");
            //1.第一種方式,單位元組讀取
            int len = 0;
            while((len = fis.read())!=-1){
                fos.write(len);//将位元組輸入流讀取出來的資料寫入輸出流指定的檔案中
            }

            //2.第二種方式,使用byte[]數組作為緩沖區讀取 (效率高)
            byte[] bytes = new byte[1024];
            int len2 = 0;
            while ((len2 = fis.read(bytes))!=-1){
                //public void write(byte b[], int off, int len) offset 開始索引  count 轉換的個數
                fos.write(bytes,0,len2);
            }

            fis.close();//關閉輸入流
            fos.close();//關閉輸出流

        }

    }
}
           

字元流

當使用位元組流讀取文本檔案時,可能會有一個小問題,就是遇到中文字元時,可能不會顯示完整的字元,那是因為一個中文字元可能占用多個位元組存儲,是以Java提供一些字元流類,以字元為機關讀寫資料,專門用于處理文本檔案

字元輸入流 Reader

Reader 抽象類是用于讀取字元流的所有類的超類,可以讀取字元資訊到記憶體中。它定義了字元輸入流的基本共性功能方法

  • public void close() 關閉此流并釋放與此流相關聯的任何系統資源
  • public int read() 從輸入流讀取一個字元
  • public int read(char[] cbuf) 從輸入流中讀取一些字元,并将它們存儲到字元數組cbuf中

FileReader類

  • FileReader extends InputStreamReader , InputStreamReader extends Reader
  • FileReader 檔案字元輸入流 (把硬碟檔案中的資料以字元的方式讀取到記憶體中)
  • 構造方法
    1. FileReader(String fileName) 建立一個新的FileReader,給定要讀取的檔案的名稱
    2. FileReader(File file) 建立一個新的FileReader,給定File讀取
package com.byxx.yunan.test.io;


import java.io.FileReader;
import java.io.IOException;

/**
 * @Author yww
 * @CreateTime 2021-02-26
 */
public class Test10 {
    public static void main(String[] args) throws IOException {
        //字元輸入流,将磁盤中的資料讀取到記憶體中
        FileReader fr = new FileReader("D:\\log\\d.txt");

        /*
           第一種讀取方式
              public int read()
         */
        int len1 = 0;
        while((len1 = fr.read())!=-1){
            System.out.print((char)len1);
        }

        /*
           第二種讀取方式,效率高
              public int read(char cbuf[])
         */
        char[] cbuf = new char[1024];
        int len2 = 0;
        while((len2 = fr.read(cbuf))!=-1){
            //public String(char value[], int offset, int count) offset 開始索引  count 轉換的個數
            System.out.print(new String(cbuf,0,len2));
        }

        //關閉資源
        fr.close();
    }
}
           

字元輸出流 Writer

Writer 抽象類是表示用于寫出字元流的所有類的超類,将指定的字元資訊寫出到目的地。它定義了位元組輸出流的基本共性功能方法

  • void write(int c) 寫入單個字元
  • void write(char[] cbuf) 寫入字元數組
  • abstract void write(char[] cbuf, int off, int len) 寫入字元數組的某一部分,off數組的開始索引,len寫的字元個數
  • void write(String str) 寫入字元串
  • void write(String str, int off, int len) 寫入字元串的某一部分,off字元串的開始索引,len寫的字元個數
  • void flush() 重新整理該流的緩沖
  • void close() 關閉此流,但要先重新整理它。

FileWriter

  • FileWriter extends OutputStreamWriter , OutputStreamWriter extends Writer
  • FileWriter 檔案字元輸出流 (将記憶體中的資料寫入磁盤中)
  • 構造方法
    1. FileWriter(File file) 給一個File對象構造一個FileWriter對象
    2. FileWriter(File file, boolean append) 給一個File對象構造一個FileWriter對象
    3. FileWriter(String fileName) 構造一個給定檔案名的FileWriter對象
    4. FileWriter(String fileName, boolean append) 構造一個FileWriter對象,給出一個帶有布爾值的檔案名,表示釋放附加寫入的資料
package com.byxx.yunan.test.io;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @Author yww
 * @CreateTime 2021-02-26
 */
public class Test11 {
    public static void main(String[] args) throws IOException {
        /*
          字元輸出流
          public FileWriter(String fileName, boolean append)
             String fileName  檔案目的地
             boolean append  是否追加寫入資料
         */
        FileWriter fw = new FileWriter("D:\\log\\e.txt",true);
        /*
          write()将資料填充到記憶體緩沖區
         */
        //void write(char[] cbuf) 寫入字元數組
        char[] cs = {'A','B','C','D','E'};
        fw.write(cs);//ABCDE

        //void write(char[] cbuf, int off, int len) 寫入字元數組的一部分,off數組的開始索引,len寫的個數
        fw.write(cs,2,3);//CDE

        fw.write("\r\n");//換行

        //void write(String str) 寫入字元串
        String str = "showme我的time ";
        fw.write(str);//showme我的time
        
        //void write(String str, int off, int len) 寫入字元串的一部分,off數組的開始索引,len寫的個數
        fw.write(str,8,4);//time


        //重新整理緩沖區資料寫入到檔案中
        fw.flush();
        //關閉資源
        fw.close();
    }
}
           

flush()方法和close()方法的差別

  • flush() 重新整理緩沖區,流對象可以繼續使用
  • close() 先重新整理緩沖區,然後通知系統釋放資源。流對象不可以再被使用了。

Properties類

Properties 繼承于 HashTable,來表示一個持久的屬性集,它使用鍵值結構存儲資料,每個鍵及其對應值都是一個字元串,該類也被許多java類使用,比如擷取系統屬性時,getProperties() 方法就是傳回一個Properties對象。

  • 構造方法
    • public Properties() 建立一個空的屬性清單
  • 基本的存儲方法
    • public Object setProperty(String key, String value) 儲存一對屬性
    • public String getProperty(String key) 使用此屬性清單中指定的鍵搜尋屬性值
    • public Set stringPropertyNames() 擷取所有key存入set集合
  • 流相關操作的方法
    • public void store(Write write, String comments) 将Properties集合中的資料以字元串輸出流的方式寫入到檔案中
    • public synchronized void load(Reader reader) 将檔案中的資料以字元串輸入流的方法讀取到集合中
    package com.byxx.yunan.test.io;
    
    import javafx.scene.chart.ValueAxis;
    
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    import java.util.Set;
    
    /**
     * Properties集合 extends HashTable集合
     *      HashTable特性:
     *          不允許空key,不允許空value
     *      Properties特性:
     *          1.key和value都是字元串
     *          2.不允許空key,不允許空value
     */
    public class Test12 {
        public static void main(String[] args) {
            store();
            load();
        }
    
        /**
         * 使用Properties類中的store(Write write,String comments)方法
         * 将集合中的資料存儲到檔案中
         */
        public static void store(){
            Properties pro = new Properties();
            pro.setProperty("張三","18歲");
            pro.setProperty("李四","19歲");
            pro.setProperty("王五","20歲");
    
            FileWriter fileWriter = null;
            try {
                //字元串輸出流
                fileWriter = new FileWriter("D:\\log\\AAA.txt");
    
                /*
                   properties的store(Write write,String comments)
                   把集合中的資料,持久化寫入硬碟中存儲
                 */
                pro.store(fileWriter,"wo shi zhu shi");//Write:字元串輸出流 comments:注釋
    
    
    
            }catch (IOException e){
                e.printStackTrace();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try{
                    fileWriter.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 使用Properties類中的load(Reader reader)方法
         * 将檔案中的資料以key,value的形式讀取到集合中
         * 特點:
         *     使用#注釋的不會讀取到集合中
         *     使用 =  或者 空格 作為key,value辨別
         * 示例:
         *     王五=20歲 或者 王五 20歲
         */
        public static void load(){
            Properties pro = new Properties();
            FileReader fileReader = null;
            try{
    
                /*
                   properties的load(Reader reader)方法
                   把硬碟中儲存的檔案(鍵值對),讀到集合中使用
                 */
                fileReader = new FileReader("D:\\log\\AAA.txt");
                pro.load(fileReader);
    
                //擷取properties集合中的資料
                Set<String> keys = pro.stringPropertyNames();
                for (String key : keys) {
                    String value = pro.getProperty(key);
                    System.out.println("key:"+key+"  value:"+value);
                }
    
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try {
                    fileReader.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    
    }
               
    • store方法将集合中的資料寫入檔案中效果示例:
Java基礎總結Java三大版本JDK , JRE , JVMHelloWorld詳解Java八大基礎資料類型類型轉換變量 ,常量 , 作用域運算符JavaDoc生成文檔Switch 多選擇結構循環結構Break ,Continue方法重載可變參數Math 數學工具類Random 随機數工具類數組Object ,Objects日期面向對象static 關鍵字詳解抽象接口N種内部類異常System類StringBuilder循環集合資料結構File遞歸IO

緩沖流

緩沖流,也叫高校流,是對4個基本的FIleXxx流的增強,是以也是4個流,按照資料類型分類:

  • 位元組緩沖流:BufferedInputStream,BufferedOutputStream
  • 字元緩沖流:BufferedReader,BufferedWriter

緩沖流的基本原理,是在建立流對象時,會建立一個内置的預設大小的緩沖區數組,通過緩沖區讀寫,減少系統IO次數,進而提高讀寫的效率

位元組緩沖流

  • 構造方法
    1. public BufferedInputStream(InputStream in) 建立一個新的緩沖位元組輸入流
    2. public BufferedOutputStream(OutputStream out) 建立一個新的緩沖位元組輸出流
package com.byxx.yunan.test.io;

import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.Buffer;

/**
 * @Author yww
 * @CreateTime 2021-02-28
 */
public class Test13 {
    public static void main(String[] args) throws IOException {
        bufferedInputStream();
        bufferedOutputStream();
    }


    /**
     * 位元組緩沖流輸入流BufferedInputStream(InputStream in)
     * @throws IOException
     */
    public static void bufferedInputStream() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\log\\a.txt"));
        //第一種方式,效率低,依次讀取檔案資料
        /*long startTime1 = System.currentTimeMillis();
        int len1 = 0;
        while((len1 = bis.read())!=-1){
            System.out.println(len1);
        }
        long endTime1 = System.currentTimeMillis();
        System.out.print(endTime1-startTime1+"毫秒");*/

        System.out.println("==========================緩沖=============================");
        //第二種方式,效率高,按數組大小一次性讀取檔案資料,做緩沖
        long startTime2 = System.currentTimeMillis();
        byte[] bytes = new byte[1024];
        int len2 = 0;
        while((len2 = bis.read(bytes))!=-1){
            System.out.print(new String(bytes,0,len2));
        }
        long endTime2 = System.currentTimeMillis();
        System.out.print(endTime2-startTime2+"毫秒");
        bis.close();
    }

    /**
     * 緩沖位元組輸出流BufferedOutputStream(OutputStream out)
     * @throws IOException
     */
    public static void bufferedOutputStream() throws IOException{
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\log\\ABC.txt"));
        bos.write("這是緩沖位元組輸出流".getBytes());
        bos.close();
    }

}
           

字元緩沖流

  • 構造方法
    1. public BufferedReader(Reader in) 建立一個新的緩沖字元輸入流
    2. public BufferedWriter(Writer out) 建立一個新的緩沖字元輸出流
package com.byxx.yunan.test.io;

import java.io.*;

/**
 * @Author yww
 * @CreateTime 2021-03-02
 */
public class Test14 {
    public static void main(String[] args) throws IOException {
        BufferedReader();
        BufferedWriter();
    }

    /**
     * 緩沖字元輸入流:
     * BufferedReader extends Reader
     *
     * 構造方法:
     *      BufferedReader(Reader in) 建立一個使用預設大小輸入緩沖區的緩沖字元輸入流
     *      BufferedReader(Reader in, int sz) 建立一個使用指定大小輸入緩沖區的緩沖字元輸入流
     *
     * 特有方法:
     *      readLine() 讀取一個文本行,如果已到達流末尾,則傳回null
     *
     * @throws IOException
     */
    public static void BufferedReader() throws IOException {
        //1.建立一個緩沖字元輸入流
        BufferedReader br = new BufferedReader(new FileReader("D:\\log\\d.txt"));
        //2.讀取資料
        //第一種方式,單個字元讀取,效率低
        /*int len1 = 0;
        while((len1 = br.read())!=-1){
            System.out.print((char)len1);
        }*/

        //第二種方式,建立緩沖數組,效率高
        /*char[] chars = new char[1024];
        int len2 = 0;
        while((len2 = br.read(chars))!=-1){
            System.out.println(new String(chars,0,len2));
        }*/

        //第三種方式,BufferedReader特有方法:readLine(),讀取到結尾為null
        String len3;
        while((len3 = br.readLine())!=null){
            System.out.println(len3);
        }
        //3.關閉資源
        br.close();
    }

    /**
     * 緩沖字元輸出流:
     * BufferedWriter extends Writer
     *
     * 構造方法:
     *      BufferedWriter(Writer out) 建立一個使用預設大小輸出緩沖區的緩沖字元輸出流
     *      BufferedWriter(Writer out,int sz) 建立一個使用給定大小輸出緩沖區的緩沖字元輸出流
     *
     *  特有方法:
     *      newLine() 換行符
     * @throws IOException
     */
    public static void BufferedWriter() throws IOException {
        //1.建立緩沖字元輸出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\log\\f.txt"));
        //2.寫入資料
        for (int i = 0; i < 10; i++) {
            bw.write("我是"+i);
            bw.newLine();//換行符
        }
        //3.将緩沖區的資料重新整理到檔案中
        bw.flush();
        //4.關閉資源
        bw.close();
    }
}
           

對文本内容進行排序

package com.byxx.yunan.test.io;

import com.sun.org.apache.bcel.internal.generic.NEW;

import java.io.*;
import java.util.Set;
import java.util.TreeMap;

/**
 * @Author yww
 * @CreateTime 2021-03-02
 */
public class Test15 {
    public static void main(String[] args) throws IOException {

        /**
         * 需求:
         * 将檔案改為正常序号填充到檔案中
         * 原檔案
         * 2.我是第二行
         * 4.我是第四行
         * 1.我是第一行
         * 3.我是第三行
         */
        //建立緩沖輸入流,讀取資料
        BufferedReader br = new BufferedReader(new FileReader("D:\\log\\f.txt"));

        TreeMap<String, String> treeMap = new TreeMap<>();
        String len;
        while((len = br.readLine())!=null){
            String number = len.substring(0, 2);//序号
            String content = len.substring(2, len.length());
            System.out.println(number+"------"+content);
            treeMap.put(number,content);
        }
        System.out.println(treeMap);
        br.close();

        /**
         * 調整後檔案
         * 1.我是第一行
         * 2.我是第二行
         * 3.我是第三行
         * 4.我是第四行
         */
        //建立緩沖輸出流,寫入資料
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\log\\g.txt"));
        Set<String> keySet = treeMap.keySet();
        for (String key : keySet) {
            String value = treeMap.get(key);
            bw.write(key+value);
            bw.newLine();
        }
        bw.close();
    }
}
           

轉換流

輸出轉換流OutputStreamWriter

  • OutputStreamWriter extends Writer
  • OutputStreamWriter 是字元流通向位元組流的橋梁:可使用指定的 charset 将要寫入流中的字元編碼成位元組。
  • 繼承自父類的共性成員方法
    1. void write(int c) 寫入單個字元
    2. void write(char[] cbuf) 寫入字元數組
    3. abstract void write(char[] cbuf, int off, int len) 寫入字元數組的某一部分,off數組的開始索引,len寫的字元個數
    4. void write(String str) 寫入字元串
    5. void write(String str, int off, int len) 寫入字元串的某一部分,off字元串的開始索引,len寫的字元個數
    6. void flush() 重新整理該流的緩沖
    7. void close() 關閉此流
  • 構造方法
    • OutputStreamWriter(OutputStream out) 建立使用預設字元編碼的 OutputStreamWriter
    • OutputStreamWriter(OutputStream out, String charsetName) 建立使用指定字元集的 OutputStreamWriter
  • 參數
    • OutputStream out : 位元組輸出流,可以用來寫轉換之後的位元組到檔案中
    • String charsetName : 指定的編碼表名稱,不區分大小寫,可以是utf-8/gbk…編碼,不指定預設使用UTF-8
package com.byxx.yunan.test.io;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
 * @Author yww
 * @CreateTime 2021-03-03
 */
public class Test16 {
    public static void main(String[] args) throws IOException{
        OutputStreamWrite();
    }

    /**
     * 轉換輸出流
     * OutputStreamWrite extends Write
     * OutputStreamWrite 可以指定輸出編碼集
     *
     * 構造方法:
     *      OutputStreamWrite(OutputStream out) 建立使用預設字元編碼的OutputStreamWrite
     *      OutputStreamWrite(OutputStream out,String charsetName) 建立使用指定字元集OutputStreamWrite
     *      參數:
     *          OutputStream out: 位元組輸出流,可以用來寫轉換之後的位元組到檔案中
     *          String charsetName: 指定的編碼表名稱,不區分大小寫,可以使用utf-8,gbk...編碼,不指定預設使用UTF-8
     */
    public static void OutputStreamWrite() throws IOException {
        /**
         * 不指定,預設使用UTF-8
         */
        long startTime1 = System.currentTimeMillis();
        //1.建立轉換流對象
        OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("D:\\log\\yyyy.txt"));
        //2.寫入資料
        for (int i = 0; i < 100000; i++) {
            osw1.write("你好,轉換流OutputStreamWriter"+i);
        }
        //3.将緩沖資料重新整理到檔案中
        osw1.flush();
        //4.關閉資源
        osw1.close();
        long endTime1 = System.currentTimeMillis();
        System.out.println("使用緩沖位元組輸出流作為構造,運作 "+(endTime1-startTime1)+" 毫秒");

        /**
         * 指定編碼集
         */
        long startTime2 = System.currentTimeMillis();
        //1.建立轉換流對象,這次指定編碼集
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("D:\\log\\aaaa.txt"),"utf-8");
        //2,寫入資料
        for (int i = 0; i < 100000; i++) {
            osw2.write("你好,轉換流OutputStreamWriter"+i);
        }
        //3.将緩沖區資料重新整理到檔案中
        osw2.flush();
        //4.關閉資源
        osw2.close();
        long endTime2 = System.currentTimeMillis();
        System.out.println("使用位元組輸出流作為構造,運作 "+(endTime2-startTime2)+" 毫秒");
    }
}
           

輸入轉換流InputStreamReader

  • InputStreamReader extends Reader
  • InputStreamReader 是字元流通向字元流的橋梁,它使用指定的 charset 讀取位元組并将其解碼為字元。
  • 繼承自父類的共性成員方法
    1. int read() 讀取單個字元并傳回
    2. int read(char[] cbuf) 一次讀取多個字元,将字元讀入數組
    3. void close() 關閉該流并釋放與之關聯的所有資源
  • 構造方法
    • InputStreamReader(InputStream in) 建立一個使用預設字元集的 InputStreamReader
    • InputStreamReader(InputStream in, String charsetName) 建立使用指定字元集的 InputStreamReader
  • 參數
    • InputStream in : 位元組輸入流,用來讀取檔案中儲存的位元組
    • String charsetName : 指定的編碼表名稱,不區分大小寫,可以是utf-8/gbk…編碼,不指定預設使用UTF-8
  • 注意事項
    • 構造方法中指定的編碼表名稱要和檔案的編碼相同,否則會發生亂碼
package com.byxx.yunan.test.io;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @Author yww
 * @CreateTime 2021-03-03
 */
public class Test17 {
    public static void main(String[] args) throws IOException{
        InputStreamReader();
    }

    /**
     * InputStreamReader extends Reader
     * InputStreamReader 是位元組流通向字元流的橋梁,它使用指定的 charset 讀取位元組并将其解碼為字元。
     *
     * 構造方法:
     *      InputStreamReader(InputStream in) 建立一個使用預設字元集的 InputStreamReader
     *      InputStreamReader(InputStream in, String charsetName) 建立使用指定字元集的 InputStreamReader
     *      參數:
     *          InputStream in: 位元組輸入流,用來讀取檔案中儲存的位元組
     *          String charsetName: 指定的編碼表名稱,不區分大小寫,可以是utf-8/gbk...編碼,不指定預設使用UTF-8
     * 注意事項:
     *      構造方法中指定的編碼表名稱要和檔案的編碼相同,否則會發生亂碼
     *
     * @throws IOException
     */
    public static void InputStreamReader() throws IOException {
        //不指定預設使用UTF-8
        //1.建立輸入轉換流
        InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\log\\aaaa.txt"));
        //2.讀取資料
        int len1 = 0;
        while((len1 = isr1.read())!=-1){
            System.out.print((char)len1);
        }
        //3.關閉資源
        isr1.close();


        //指定字元編碼集,UTF-8
        //1.建立輸入轉換流
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream("D:\\log\\aaaa.txt"),"utf-8");
        //2.讀取資料
        int len2 = 0;
        while((len2 = isr2.read())!=-1){
            System.out.print((char)len2);
        }
        //3.關閉資源
        isr2.close();
    }
}
           

序列化流

ObjectOutputStream類

ObjectOutputStream 類,将Java對象的原始資料類型寫出到檔案,實作對象的持久存儲。

  • 構造方法
    1. public ObjectOutputStream(OutputStream out) : 建立一個指定OutputStream的ObjectOutputStream。

ObjectInputStream類

ObjectInputStream 類,将之前使用ObjectOutputStream序列化的原始資料恢複為對象。

  • 構造方法
    1. public ObjectInputStream(InputStream in) : 建立一個指定InputStream的ObjectInputStream
package com.byxx.yunan.test.io;

import java.io.*;

/**
 * @Author yww
 * @CreateTime 2021-03-04
 */
public class Test18 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /**
         * 序列化輸出流
         * 将對象寫入檔案中
         * ObjectOutputStream extends OutputStream
         */
        //1.建立ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\log\\tttt.txt"));
        //2.将對象寫入到檔案中 (如果對象沒有序列化,則會報java.io.NotSerializableException異常)
        oos.writeObject(new Survey("測試問卷",18));
        //3.釋放資源
        oos.close();

        /**
         * 序列化輸入流
         * 将序列化輸出流寫入檔案的資料讀取出來
         * ObjectInputStream extends InputStream
         */
        //1.建立ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\log\\tttt.txt"));
        //2.讀取檔案中資料
        Object o = ois.readObject();//讀取一個對象
        Survey survey = (Survey) o;
        System.out.println(survey.getName());
        //3.關閉資源
        ois.close();

    }
}

//問卷類
class Survey implements Serializable {

    private String name;
    private Integer age;

    public Survey() {
    }

    public Survey(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
           
  • transient 瞬态關鍵字
    //使用transient關鍵字修飾不會被序列号
    private transient Integer ages;
               

列印流

PrintStream類

  • 構造方法
    1. public PrintStream(String fileName) : 使用指定的檔案名建立一個新的列印流。
package com.byxx.yunan.test.io;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/**
 * 列印流
 * java.io.PrintStream extends OutputStream
 *      PrintStream 為其他輸出流添加了功能,使它們能夠友善的列印各種資料值表示形式
 * PrintStream特點:
 *      1.隻負責資料的輸出,不負責資料的讀取
 *      2.與其他輸出流不同,PrintStream永遠不會抛出IOException
 *      3.有特有的方法,print,println
 *          void print(任意類型的值)
 *          void println(任意類型的值并換行)
 * 構造方法:
 *      PrintStream(File file) 輸出的目的地是一個檔案
 *      PrintStream(OutputStream out) 輸出的目的地是一個位元組輸出流
 *      PrintStream(String fileName) 輸出目的地是一個檔案路徑
 * 注意:
 *      如果使用繼承自父類的write方法寫資料,那麼檢視資料的時候會查詢編碼表 97->a
 *      如果使用自己特有的方法print/println方法寫資料,寫的資料原樣輸出 97->97
 */
public class Test19 {
    public static void main(String[] args) throws FileNotFoundException {
        //1.建立列印流
        PrintStream ps = new PrintStream("D:\\log\\BBBB.txt");
        //2.使用父類的write()方法寫入資料,那麼檢視資料的時候會查詢編碼表 97->a
        ps.write(97);//列印a
        //3.使用自身print/println方法,寫的資料原樣輸出 97->97
        ps.println(97);//列印97
        ps.println("abc");//列印abc
        ps.println("這是列印流");//列印 列印流
        //4.關閉資源
        ps.close();
        /*
           列印結果:
                a97
                abc
                這是列印流
         */
    }
}