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詳解
- 随便建立一個檔案夾,存放代碼
- 建立一個java檔案
- 檔案字尾名為 .java
- HelloWorld.java
- [注意點] 系統可能沒有顯示檔案字尾名,我們需要手動打開
- 編寫代碼
public class HelloWorld{ public static void main(String[] args){ System.out.print("Hello,World!"); } }
- 編譯 javac java檔案,會生成一個class檔案
- 運作class 檔案, java class檔案 (運作class檔案不用加class字尾)
Java八大基礎資料類型
資料類型
- 強類型語言
- 要求變量的使用要嚴格符合規定,所有變量都必須先定義後才能使用
- Java的資料類型分為兩大類
- 基本類型 (primitive type)
- 引用類型 (reference type)
-
整型(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 也是我們使用的最多的一個整型類型。
-
浮點型(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” 。
浮點型的資料是不能完全精确的,有時候在計算時可能出現小數點最後幾位出現浮動,這時正常的。
-
字元型(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 。
- 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
需要文檔注釋
- 生成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? 弄啥嘞?");
}
}
}
驗證字元本質還是數字 (檢視編譯後源碼)
編譯後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 循環
- 主要用于周遊數組和集合的增強型 for 循環
int[] numbers = {10,20,30,40,50}; for(int x: numbers){ System.out.println(x); }
- while 循環
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 } }
反轉數組
- 第一種方法
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)); } }
- 第二種方法
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 */ } }
- 二維數組結構解析
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
- 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; }
super,this
super注意點:
1. super 調用父類的構造方法,必須在構造方法的第一個
2. super 必須隻能出現在子類的方法或者構造方法中
3. super 和 this 不能同時調用構造方法
VS this:
代表的對象不同:
this:本身調用者這個對象
super:代表父類對象的應用
- 前提:
this:沒有繼承也可以使用
super:隻能在繼承條件中才可以使用構造方法
- 構造方法:
this() ; 本身的構造
super() ; 父類的構造
重寫
重寫:需要有繼承關系,子類重寫父類的方法!重寫:子類的方法和父類必須一緻:方法體不同!
- 方法名必須相同
- 參數清單必須相同
- 修飾符:範圍可以擴大但不能縮小 public > protected > default > private
- 抛出的異常:範圍,可以被縮小,但不能擴大 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的容量,會自動的擴容。
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(); 傳回疊代的下一個元素
疊代器的使用步驟
- 使用集合的方法iterator() 擷取疊代器的實作類對象,使用Iterator接口接收(多态)
- 使用Iterator接口中的方法hasNext判斷還有沒有下一個元素
- 使用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()); } } }
集合
Collection頂級集合接口
- boolean add (E e); 向集合中添加元素
- boolean remove (E e); 删除集合中的某個元素
- void clear (); 清空集合中所有的元素
- boolean contains (E e); 判斷集合中是否包含某個元素
- boolean isEmpty (); 判斷集合是否為空
- int size (); 擷取集合的長度
- Object[] toArray (); 将集合轉成一個數組
List
- List接口特點:
- 有序的集合,存儲元素和取出元素的順序是一緻的(存儲123,取出123)
- 有索引,包含了一些帶索引的方法
- 允許存儲重複的元素
- 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集合存儲元素不重複的原理
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集合的特點:
- Map集合是一個雙列集合,一個元素包含兩個值 (一個key,一個value)
- Map集合中的元素,key和value的資料類型可以相同,也可以不同
- Map集合中的元素,key是不允許重複的,value是可以重複的 (如果出現key重複,後put重複的value值會替換之前put的value)
- Map集合中的元素,key和value是一 一對應的
- Map接口常用方法
- public V put(K key,V value); 把指定的鍵與指定的值添加到Map集合中
- public V remove(Object key); 把指定的鍵所對應的鍵值對元素在Map集合中删除,傳回被删除元素的值
- public V get(Object key); 根據指定的鍵,在Map集合中擷取對應的值
- boolean containsKey(Object key); 判斷集合中是否包含指定的鍵
- public Set keySet(); 擷取Map集合中所有的鍵,存儲到Set集合中
- 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集合特點:
-
HashMap集合底層是哈希表,查詢效率快
JDK1.8之前:數組 + 連結清單
JDK1.8之後:數組 + 連結清單 + 紅黑樹
- HashMap集合是一個無序的集合,存儲元素和取出元素的順序有可能不一緻
-
- HashMap存儲自定義類型鍵值
- Map集合保證key是唯一的
- 作為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集合的特點:
- LinkedHashMap集合底層是哈希表 + 連結清單 (保證疊代的順序)
- 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特點:
- 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差別
-
HashTable 底層是一個哈希表,是一個線程安全的集合,是單線程集合,速度慢
HashMap 底層是一個哈希表,是一個線程不安全的集合,是多線程的集合,速度快
-
HashTable 不能存儲 null 鍵 null 值
HashMap(包括其他集合) 可以存儲 null 鍵 null 值
- 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,又稱堆棧,它是運算受限的線性表,其限制是僅允許在标的一端進行插入和删除操作,不允許在其他任何位置進行添加,查找,删除等操作。
簡單的來說:采用該結構的集合,對元素的存取有如下的特點
- 先進後出(即,存進去的元素,要在它後面的元素依次取出後,才能取出該元素)。例如,子彈壓進彈夾,先壓進去的子彈在下面,後壓進去的子彈在上面,當開槍時,先彈出上面的子彈,然後才能彈出下面的子彈。
- 棧的入口,出口都是棧的頂端位置。
隊列
- 隊列:queue,簡稱隊,它同堆棧一樣,也是一種運算受限的線性表,其限制是僅允許在表的一端進行插入,而在表的另一端進行删除。
簡單的說,采用該結構的集合,對元素的存取有如下的特點:
- 先進先出(即,存進去的元素,要在它前面的元素依次取出來後,才能取出該元素)。例如,小火車過山洞,車頭先進去,車尾後進去;車頭先出來,車尾後出來。
數組
- 數組:Array,是有序的元素序列,數組是在記憶體中開辟一段連續的空間,并在此空間放元素,就像是一排出租屋,有100個房間,從001到100每個房間都有固定編号,通過編号就可以快速找到租房子的人。
簡單的說,采用該結構的集合,對元素的存取有如下的特點:
- 查找元素快:通過索引,可以快速通路指定位置的元素。
- 增删元素慢
- 指定索引位置增加元素,需要建立一個新數組,将指定新元素存儲在指定索引位置,再把原數組元素根據索引,複制到新數組對應索引的位置。
連結清單
- 連結清單:linked list,由一系列節點node(連結清單中每一個元素稱為節點)組成,節點可以在運作時動态生成。每個節點包括兩個部分:一個是存儲資料元素的資料域,另一個是存儲下一個節點位址的指針域,連結清單結構有單向連結清單與雙向連結清單
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 檔案位元組輸出流 (把記憶體中的資料寫入到硬碟的檔案中)
- 構造方法
- FileOutputStream(String name) 建立一個向具有指定名稱的檔案中寫入資料的輸出檔案流
- FileOutputStream(String name, boolean append) 建立一個向具有指定 name 的檔案中寫入資料的檔案輸出流,是否開啟資料寫入追加
- FileOutputStream(File file) 建立一個向指定File對象表示的檔案中寫入資料的檔案輸出流
- FileOutputStream(File file, boolean append) 建立一個向指定 File 對象表示的檔案中寫入資料的檔案輸出流,是否開啟資料寫入追加
參數:寫入資料的目的
String name :目的地是一個檔案的路徑
File file :目的地是一個檔案
構造方法的作用:
- 建立一個FileOutputStream對象
- 會根據構造方法中傳遞的檔案 / 檔案路徑,建立一個空的檔案
- 會把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 檔案位元組輸出流 (從檔案中讀取位元組)
- 構造方法
- FileInputStream(File file) 通過打開與實際檔案的連接配接建立一個FileInputStream,該檔案由檔案系統中的File對象 file命名
- 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 檔案字元輸入流 (把硬碟檔案中的資料以字元的方式讀取到記憶體中)
- 構造方法
- FileReader(String fileName) 建立一個新的FileReader,給定要讀取的檔案的名稱
- 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 檔案字元輸出流 (将記憶體中的資料寫入磁盤中)
- 構造方法
- FileWriter(File file) 給一個File對象構造一個FileWriter對象
- FileWriter(File file, boolean append) 給一個File對象構造一個FileWriter對象
- FileWriter(String fileName) 構造一個給定檔案名的FileWriter對象
- 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方法将集合中的資料寫入檔案中效果示例:
緩沖流
緩沖流,也叫高校流,是對4個基本的FIleXxx流的增強,是以也是4個流,按照資料類型分類:
- 位元組緩沖流:BufferedInputStream,BufferedOutputStream
- 字元緩沖流:BufferedReader,BufferedWriter
緩沖流的基本原理,是在建立流對象時,會建立一個内置的預設大小的緩沖區數組,通過緩沖區讀寫,減少系統IO次數,進而提高讀寫的效率
位元組緩沖流
- 構造方法
- public BufferedInputStream(InputStream in) 建立一個新的緩沖位元組輸入流
- 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();
}
}
字元緩沖流
- 構造方法
- public BufferedReader(Reader in) 建立一個新的緩沖字元輸入流
- 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 将要寫入流中的字元編碼成位元組。
- 繼承自父類的共性成員方法
- 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() 關閉此流
- 構造方法
- 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 讀取位元組并将其解碼為字元。
- 繼承自父類的共性成員方法
- int read() 讀取單個字元并傳回
- int read(char[] cbuf) 一次讀取多個字元,将字元讀入數組
- 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對象的原始資料類型寫出到檔案,實作對象的持久存儲。
- 構造方法
- public ObjectOutputStream(OutputStream out) : 建立一個指定OutputStream的ObjectOutputStream。
ObjectInputStream類
ObjectInputStream 類,将之前使用ObjectOutputStream序列化的原始資料恢複為對象。
- 構造方法
- 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類
- 構造方法
- 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
這是列印流
*/
}
}