常用API、正則表示式,泛型、Collection集合API
主要內容
- Date類
- Java是面向物件的思想,會用一個類來代表一個事物。
- Date代表了系統當前此刻日期物件!年月日時分秒。
- DateFormat類
- 日期格式化類,認為日期物件拿到的時間是不好看的!
- 日期格式化類可以把時間格式化成我們喜歡的格式。
- 日期格式化類可以把字串時間解析成日期物件!! "2019-10-01 09:28:00"
- Calendar類
- 日曆類,代表了此刻日期物件對應的日曆物件。日曆的資訊更加的豐富。
- System類
- 代表了當前JVM虛擬機器對應的作業系統物件。
- 可以拿系統時間。
- 可以讓程式退出JVM虛擬機器,讓程式立即死亡!!
- 可以做陣列拷貝。
- StringBuilder類
- String類不適合做字串的拼接,增刪等運算。不可變字串,增刪效能較差!
- StringBuillder非常適合做字串的增刪改查操作,效能更好!!
- 包裝類
- 一切皆物件。
- int Integer int age = 21; Integer age1 = 21;
- float Float
- double Double
- 泛型
- ArrayLIst
lists = new ArrayList<>();
- ArrayLIst
- Collection集合:List , Map , Set
- 三天的集合框架(重點內容,開發必用的!!)
教學目標
-
能夠使用日期類輸出當前日期
- Date d = new Date();
- System.out.println(d);
-
能夠使用將日期格式化為字串的方法
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- String rs = sdf.format(“日期物件”)
- String rs = sdf.format("時間毫秒值")
-
能夠使用將字串轉換成日期的方法
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- String str = "2019-11-11 11:11:11";
- Data d = sdf.parse(str );
- System.out.println(d);
-
能夠使用System類的陣列複製方法
// 3.陣列拷貝: int[] arrs1 = {10 , 20 , 30 , 40 , 50 , 60 , 70 , 80}; // arrs2 = [ 0 , 0 , 0 , 0 , 0 , 0] // arrs2 = [0 , 0 , 30 , 40 , 50 , 0] // 希望把第一個陣列的 30 , 40 , 50賦值到第二個陣列! int[] arrs2 = new int[6]; /** arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 引數一:原陣列。 引數二:從原陣列哪個位置開始複製 引數三:目標陣列 引數四:複製到目標陣列的哪個位置開始。 引數五:複製多少個! */ System.arraycopy(arrs1, 2 ,arrs2 , 2 , 3); System.out.println(Arrays.toString(arrs2));
-
能夠使用System類獲取當前毫秒時刻值
long time = System.currentTimeMillis();
-
能夠說出使用StringBuilder類可以解決的問題
- 可以做字串的運算(拼接,增刪,反轉)
-
能夠使用StringBuilder進行字串拼接操作
- append
-
能夠說出8種基本型別對應的包裝類名稱
-
int Integer
-
char Character
基本資料型別 包裝類 byte Byte short Short int Integer(特殊) long Long float Float double Double char Character(特殊) boolean Boolean
-
-
能夠說出自動裝箱、自動拆箱的概念
自動裝箱:可以直接把基本資料型別的變數或者值賦值給對應的包裝類物件。
自動拆箱:可以把包裝類的物件賦值給基本資料型別的變數。
```
- 能夠將字串轉換為對應的基本型別
```properties
功能3: 把字串型別的數字轉化成對應的基本資料型別的值!!(真的有用,而且挺重要)
Xxxx.parseXxxx("字串型別的數字")
Xxxx.valueOf("字串型別的數字"):推薦使用的!
-
能夠將基本型別轉換為對應的字串
// 功能2: 包裝類可以把基本資料型別的值轉換成字串。 // 1.把基本資料型別的值轉換成字串:toString() Integer num = 23 ; String numStr1 = num.toString(); System.out.println(numStr1+1); // 231 // 2.把基本資料型別的值轉換成字串: Integer num1 = 23 ; String num1Str1 = Integer.toString(num1); System.out.println(num1Str1+1); // 231 // 3.把基本資料型別的值轉換成字串: Integer num2 = 23 ; String num2Str1 = num2 + "" ; //常見做法! System.out.println(num2Str1+1); // 231
-
能夠說出Collection集合的常用功能
Collection集合作為集合的根類,它的功能是一切集合都可以直接使用的。 - public boolean add(E e): 把給定的物件新增到當前集合中 。 - public void clear() :清空集合中所有的元素。 - public boolean remove(E e): 把給定的物件在當前集合中刪除。 - public boolean contains(Object obj): 判斷當前集合中是否包含給定的物件。 - public boolean isEmpty(): 判斷當前集合是否為空。 - public int size(): 返回集合中元素的個數。 - public Object[] toArray(): 把集合中的元素,儲存到陣列中
-
能夠使用泛型建立集合物件
ArrayList<String> lists = new ArrayList<>(); // JDK 1.7之後泛型的簡化寫法! ArrayList<Integer> lists1 = new ArrayList<>();// JDK 1.7之後泛型的簡化寫法!
-
能夠理解泛型上下限
- ? extends Car : ?必須是Car的子類或者本身 。 上限
- ? super Car : ?必須是Car的父類或者本身 。 下限 不用的!!
-
能夠闡述泛型萬用字元的作用
- ? 可以在使用泛型的時候,代表接收一切型別
第一章 DateFormat類
java.text.DateFormat
是日期/時間格式化子類的抽象類,我們通過這個類可以幫我們完成日期和文字之間的轉換,也就是可以在Date物件與String物件之間進行來回轉換。
- 格式化:按照指定的格式,把Date物件轉換為String物件。(格式化時間)
- 解析:按照指定的格式,把String物件轉換為Date物件。(解析字串時間)
1.1 構造方法
由於DateFormat為抽象類,不能直接使用,所以需要常用的子類java.text.SimpleDateFormat
。這個類需要一個模式(格式)來指定格式化或解析的標準。構造方法為:
public SimpleDateFormat(String pattern)
:用給定的模式和預設語言環境的日期格式符號構造SimpleDateFormat。引數pattern是一個字串,代表日期時間的自定義格式。
1.2 格式規則
常用的格式規則為:
標識字母(區分大小寫) | 含義 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 時 |
m | 分 |
s | 秒 |
EEE | 周 |
a | 上午/下午 |
備註:更詳細的格式規則,可以參考SimpleDateFormat類的API文件。
1.3 常用方法
DateFormat類的常用方法有:
-
public String format(Date date)
:將Date物件格式化為字串。 -
public String format(time)
:將時間戳time格式化為字串 -
public Date parse(String source)
:將字串解析為Date物件。public class SimpleDateFormatDemo { public static void main(String[] args) throws ParseException { //格式化:從 Date 到 String Date d = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String s = sdf.format(d); System.out.println(s); // 格式化:從時間戳 到 String System.out.println(sdf.format(d.getTime())); System.out.println("--------"); //從 String 到 Date String ss = "2048-08-09 11:11:11"; //ParseException SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date dd = sdf2.parse(ss); System.out.println(dd); } }
面試題:“2019-11-04 09:30:30”往後1天15小時30分29秒後的時間是多少
```java
// 面試題:“2019-11-04 09:30:30”往後1天15小時30分29秒後的時間是多少
// 定義一個字串時間
String date = "2019-11-04 09:30:30";
// 將字串的時間解析成Date日期物件
// 注意:引數必須與被解析的時間完全一致,否則報錯
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date newDate = sdf.parse(date);
// 得到日期物件的時間戳 + 往後走1天15小時30分29秒
// 29加上L轉換成long來計算更安全
long time = newDate.getTime() + 29L*1000 + 30L*60*1000 + 39L*60*60*1000;
// 把時間戳轉換成字串的時間形式
System.out.println(sdf.format(time));
```
小結:DateFormat可以將Date物件和字串相互轉換。
第二章 Calendar類
2.1 概述
-
java.util.Calendar類表示一個“日曆類”,可以進行日期運算。它是一個抽象類,不能建立物件,我們可以使用它的子類:java.util.GregorianCalendar類。
-
有兩種方式可以獲取GregorianCalendar物件:
-
直接建立GregorianCalendar物件;
-
通過Calendar的靜態方法getInstance()方法獲取GregorianCalendar物件【本次課使用】
Calendar rightNow = Calendar.getInstance();
-
2.2 常用方法
方法名 | 說明 |
---|---|
public static Calendar getInstance() | 獲取一個它的子類GregorianCalendar物件。(單例類) |
public int get(int field) | 獲取某個欄位的值。field引數表示獲取哪個欄位的值, 可以使用Calender中定義的常量來表示: Calendar.YEAR : 年 Calendar.MONTH :月 Calendar.DAY_OF_MONTH:月中的日期 Calendar.HOUR:小時 Calendar.MINUTE:分鐘 Calendar.SECOND:秒 Calendar.DAY_OF_WEEK:星期 |
public void set(int field,int value) | 設定某個欄位的值 |
public void add(int field,int amount) | 為某個欄位增加/減少指定的值 |
2.3 get方法示例
```java
public class Demo {
public static void main(String[] args) {
//1.獲取一個GregorianCalendar物件
Calendar instance = Calendar.getInstance();//獲取子類物件
//2.列印子類物件
System.out.println(instance);
//3.獲取屬性
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH) + 1;//Calendar的月份值是0-11
int day = instance.get(Calendar.DAY_OF_MONTH);
int hour = instance.get(Calendar.HOUR);
int minute = instance.get(Calendar.MINUTE);
int second = instance.get(Calendar.SECOND);
int week = instance.get(Calendar.DAY_OF_WEEK);//返回值範圍:1--7,分別表示:"星期日","星期一","星期二",...,"星期六"
System.out.println(year + "年" + month + "月" + day + "日" +
hour + ":" + minute + ":" + second);
System.out.println(getWeek(week));
}
//查表法,查詢星期幾
public static String getWeek(int w) {//w = 1 --- 7
//做一個表(陣列)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
```
2.4 set方法示例:
public class Demo {
public static void main(String[] args) {
//設定屬性——set(int field,int value):
Calendar c1 = Calendar.getInstance();//獲取當前日期
//計算班長出生那天是星期幾(假如班長出生日期為:1998年3月18日)
c1.set(Calendar.YEAR, 1998);
c1.set(Calendar.MONTH, 3 - 1);//轉換為Calendar內部的月份值
c1.set(Calendar.DAY_OF_MONTH, 18);
int w = c1.get(Calendar.DAY_OF_WEEK);
System.out.println("班長出生那天是:" + getWeek(w));
}
//查表法,查詢星期幾
public static String getWeek(int w) {//w = 1 --- 7
//做一個表(陣列)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
```
## 2.5 add方法示例:
```java
// 讓日曆往後走多少天
public class Demo {
public static void main(String[] args) {
//計算200天以後是哪年哪月哪日,星期幾?
Calendar c2 = Calendar.getInstance();//獲取當前日期
c2.add(Calendar.DAY_OF_MONTH, 200);//日期加200
int y = c2.get(Calendar.YEAR);
int m = c2.get(Calendar.MONTH) + 1;//轉換為實際的月份
int d = c2.get(Calendar.DAY_OF_MONTH);
int wk = c2.get(Calendar.DAY_OF_WEEK);
System.out.println("200天后是:" + y + "年" + m + "月" + d + "日" + getWeek(wk));
}
//查表法,查詢星期幾
public static String getWeek(int w) {//w = 1 --- 7
//做一個表(陣列)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
```
# 第三章 Math類
## 3.1 概述
- java.lang.Math(類): Math包含執行基本數字運算的方法。
- 它不能建立物件,它的構造方法被“私有”了。因為他內部都是“靜態方法”,通過“類名”直接呼叫即可。
## 3.2 常用方法
| 方法名 | 說明 |
| -------------------------------------------- | ------------------- |
| public static int abs(int a) | 獲取引數a的絕對值: |
| public static double ceil(double a) | 向上取整 |
| public static double floor(double a) | 向下取整 |
| public static double pow(double a, double b) | 獲取a的b次冪 |
| public static long round(double a) | 四捨五入取整 |
## 3.3 示例程式碼
```java
public class Demo {
public static void main(String[] args) {
System.out.println("-5的絕對值:" + Math.abs(-5));//5
System.out.println("3.4向上取整:" + Math.ceil(3.4));//4.0
System.out.println("3.4向下取整:" + Math.floor(3.4));//3.0
System.out.println("2的8次冪:" + Math.pow(2, 8));//256.0
System.out.println("3.2四捨五入:" + Math.round(3.2));//3
System.out.println("3.5四捨五入:" + Math.round(3.5));//4
}
}
```
# 第四章 System
## 4.1 概述
`java.lang.System`類中提供了大量的靜態方法,可以獲取與系統相關的資訊或系統級操作。
## 4.2 常用方法
| 方法名 | 說明 |
| ---------------------------------------- | ------------------------------------------------ |
| public static void exit(int status) | 終止當前執行的 Java 虛擬機器,非零表示異常終止 |
| public static long currentTimeMillis() | 返回當前時間(以毫秒為單位) |
## 4.3 練習
在控制檯輸出1-10000,計算這段程式碼執行了多少毫秒
```java
import java.util.Date;
//驗證for迴圈列印數字1-9999所需要使用的時間(毫秒)
public class SystemDemo {
public static void main(String[] args) {
//獲取當前時間毫秒值
System.out.println(System.currentTimeMillis());
//計算程式執行時間
long start = System.currentTimeMillis();
for (int i = 1; i <= 10000; i++) {
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("共耗時毫秒:" + (end - start));
}
}
```
# 第五章 BigDecimal類
## 5.1 引入
浮點數做運算精度問題;
看程式說結果:
```java
public static void main(String[] args) {
System.out.println(0.09 + 0.01);
System.out.println(1.0 - 0.32);
System.out.println(1.015 * 100);
System.out.println(1.301 / 100);
}
```
## 5.2 概述
| 相關內容 | 具體描述 |
| -------- | :----------------------------------------------------------- |
| 包 | java.math 使用時需要導包 |
| 類宣告 | public class BigDecimal extends Number implements Comparable<BigDecimal> |
| 描述 | BigDecimal類提供了算術,縮放操作,舍入,比較,雜湊和格式轉換的操作。提供了更加精準的資料計算方式 |
## 5.3 構造方法
| 構造方法名 | 描述 |
| ---------------------- | ----------------------------------------------- |
| BigDecimal(double val) | 將double型別的資料封裝為BigDecimal物件 |
| BigDecimal(String val) | 將 BigDecimal 的字串表示形式轉換為 BigDecimal |
注意:推薦使用第二種方式,第一種存在精度問題;
> 建立物件的方式(最好的方式):
```java
// public static BigDecimal valueOf(double val); // 包裝浮點數成為大資料物件
public class BigDecimalDemo {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
// 把浮點數轉換成大資料物件
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);
// BigDecimal只是解決精度問題的手段,double資料才是我們的目的!
double rs = c1.doubleValue();
System.out.println(rs);
}
}
```
## 5.4 常用方法
BigDecimal類中使用最多的還是提供的進行四則運算的方法,如下:
| 方法宣告 | 描述 |
| -------------------------------------------- | ---------------------------- |
| public BigDecimal add(BigDecimal value) | 加法運算 |
| public BigDecimal subtract(BigDecimal value) | 減法運算 |
| public BigDecimal multiply(BigDecimal value) | 乘法運算 |
| public BigDecimal divide(BigDecimal value) | 除法運算 |
| public double doubleValue() | 把BigDecimal轉換成double型別 |
注意:對於divide方法來說,如果除不盡的話,就會出現java.lang.ArithmeticException異常。此時可以使用divide方法的另一個過載方法;
> BigDecimal divide(BigDecimal divisor, int scale, int roundingMode): divisor:除數對應的BigDecimal物件;scale:精確的位數;roundingMode取捨模式
> 小結:Java中小數運算有可能會有精度問題,如果要解決這種精度問題,可以使用BigDecimal
# 第六章 正則表示式
## 6.1 正則表示式的概念及演示
- 在Java中,我們經常需要驗證一些字串,例如:年齡必須是2位的數字、使用者名稱必須是8位長度而且只能包含大小寫字母、數字等。正則表示式就是用來驗證各種字串的規則。它內部描述了一些規則,我們可以驗證使用者輸入的字串是否匹配這個規則。
- 先看一個不使用正則表示式驗證的例子:下面的程式讓使用者輸入一個QQ號碼,我們要驗證:
- QQ號碼必須是5--15位長度
- 而且必須全部是數字
- 而且首位不能為0
```java
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入你的QQ號碼:");
String qq = sc.next();
System.out.println(checkQQ(qq));
}
//我們自己編寫程式碼,驗證QQ號碼
private static boolean checkQQ(String qq) {
//1.驗證5--15位
if(qq.length() < 5 || qq.length() > 15){
return false;
}
//2.必須都是數字;
for(int i = 0;i < qq.length() ; i++){
char c = qq.charAt(i);
if(c < '0' || c > '9'){
return false;
}
}
//3.首位不能是0;
char c = qq.charAt(0);
if(c == '0'){
return false;
}
return true;//驗證通過
}
}
```
- 使用正則表示式驗證:
```java
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入你的QQ號碼:");
String qq = sc.next();
System.out.println(checkQQ2(qq));
}
//使用正則表示式驗證
private static boolean checkQQ2(String qq){
String regex = "[1-9]\\d{4,14}";//正則表示式
return qq.matches(regex);
}
}
```
上面程式checkQQ2()方法中String型別的變數regex就儲存了一個"正則表示式 ",而這個正則表示式就描述了我們需要的三個規則。matches()方法是String類的一個方法,用於接收一個正則表示式,並將"本物件"與引數"正則表示式"進行匹配,如果本物件符合正則表示式的規則,則返回true,否則返回false。
**我們接下來就重點學習怎樣寫正則表示式**
## 6.2 正則表示式-字元類
- 語法示例:
1. \[abc\]:代表a或者b,或者c字元中的一個。
2. \[^abc\]:代表除a,b,c以外的任何字元。
3. [a-z]:代表a-z的所有小寫字元中的一個。
4. [A-Z]:代表A-Z的所有大寫字元中的一個。
5. [0-9]:代表0-9之間的某一個數字字元。
6. [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之間的任意一個字元。
7. [a-dm-p]:a 到 d 或 m 到 p之間的任意一個字元。
- 程式碼示例:
```java
public class Demo {
public static void main(String[] args) {
String str = "ead";
//1.驗證str是否以h開頭,以d結尾,中間是a,e,i,o,u中某個字元
String regex = "h[aeiou]d";
System.out.println("1." + str.matches(regex));
//2.驗證str是否以h開頭,以d結尾,中間不是a,e,i,o,u中的某個字元
regex = "h[^aeiou]d";
System.out.println("2." + str.matches(regex));
//3.驗證str是否a-z的任何一個小寫字元開頭,後跟ad
regex = "[a-z]ad";
System.out.println("3." + str.matches(regex));
//4.驗證str是否以a-d或者m-p之間某個字元開頭,後跟ad
regex = "[[a-d][m-p]]ad";
System.out.println("4." + str.matches(regex));
}
}
```
## 6.3 正則表示式-邏輯運算子
- 語法示例:
1. &&:並且
2. | :或者
- 程式碼示例:
```java
public class Demo {
public static void main(String[] args) {
String str = "had";
//1.要求字串是小寫子音字元開頭,後跟ad
String regex = "[a-z&&[^aeiou]]ad";
System.out.println("1." + str.matches(regex));
//2.要求字串是aeiou中的某個字元開頭,後跟ad
regex = "[a|e|i|o|u]ad";//這種寫法相當於:regex = "[aeiou]ad";
System.out.println("2." + str.matches(regex));
}
}
```
## 6.4 正則表示式-預定義字元
- 語法示例:
1. "." : 匹配任何字元。
2. "\d":任何數字[0-9]的簡寫;
3. "\D":任何非數字\[^0-9\]的簡寫;
4. "\s": 空白字元:[ \t\n\x0B\f\r] 的簡寫
5. "\S": 非空白字元:\[^\s\] 的簡寫
6. "\w":單詞字元:[a-zA-Z_0-9]的簡寫
7. "\W":非單詞字元:\[^\w\]
- 程式碼示例:
```java
public class Demo {
public static void main(String[] args) {
String str = "258";
//1.驗證str是否3位數字
String regex = "\\d\\d\\d";
System.out.println("1." + str.matches(regex));
//2.驗證手機號:1開頭,第二位:3/5/8,剩下9位都是0-9的數字
str = "13513153355";//要驗證的字串
regex = "1[358]\\d\\d\\d\\d\\d\\d\\d\\d\\d";//正則表示式
System.out.println("2." + str.matches(regex));
//3.驗證字串是否以h開頭,以d結尾,中間是任何字元
str = "had";//要驗證的字串
regex = "h.d";//正則表示式
System.out.println("3." + str.matches(regex));
//4.驗證str是否是:had.
str = "had.";//要驗證的字串
regex = "had\\.";//\\.代表'.'符號,因為.在正則中被預定義為"任意字元",不能直接使用
System.out.println("4." + str.matches(regex));
}
}
```
## 6.5 正則表示式-數量詞
- 語法示例:
1. X? : 0次或1次
2. X* : 0次到多次
3. X+ : 1次或多次
4. X{n} : 恰好n次
5. X{n,} : 至少n次
6. X{n,m}: n到m次(n和m都是包含的)
- 程式碼示例:
```java
public class Demo {
public static void main(String[] args) {
String str = "";
//1.驗證str是否是三位數字
str = "012";
String regex = "\\d{3}";
System.out.println("1." + str.matches(regex));
//2.驗證str是否是多位數字
str = "88932054782342";
regex = "\\d+";
System.out.println("2." + str.matches(regex));
//3.驗證str是否是手機號:
str = "13813183388";
regex = "1[358]\\d{9}";
System.out.println("3." + str.matches(regex));
//4.驗證小數:必須出現小數點,但是隻能出現1次
String s2 = "3.1";
regex = "\\d*\\.{1}\\d+";
System.out.println("4." + s2.matches(regex));
//5.驗證小數:小數點可以不出現,也可以出現1次
regex = "\\d+\\.?\\d+";
System.out.println("5." + s2.matches(regex));
//6.驗證小數:要求匹配:3、3.、3.14、+3.14、-3.
s2 = "-3.";
regex = "[+-]\\d+\\.?\\d*";
System.out.println("6." + s2.matches(regex));
//7.驗證qq號碼:1).5--15位;2).全部是數字;3).第一位不是0
s2 = "1695827736";
regex = "[1-9]\\d{4,14}";
System.out.println("7." + s2.matches(regex));
}
}
```
## 6.6 正則表示式-分組括號( )
```java
public class Demo {
public static void main(String[] args) {
String str = "DG8FV-B9TKY-FRT9J-99899-XPQ4G";
//驗證這個序列號:分為5組,每組之間使用-隔開,每組由5位A-Z或者0-9的字元組成
String regex = "([A-Z0-9]{5}-){4}[A-Z0-9]{5}";
System.out.println(str.matches(regex));
}
}
```
## 6.7 String的split方法中使用正則表示式
- String類的split()方法原型:
```java
public String[] split(String regex)//引數regex就是一個正則表示式。可以將當前字串中匹配regex正則表示式的符號作為"分隔符"來切割字串。
```
- 程式碼示例:
```java
public class RegexDemo4 {
public static void main(String[] args) {
// 1、split基礎用法
String names = "賈乃亮,王寶強,陳羽凡";
// 以“,”分割
String[] nameArrs = names.split(",");
// print(nameArrs);
// 2、split結合正則表示式分割
String names1 = "賈乃亮112312a3王寶強12312s35d35陳羽凡";
String[] nameArrs1 = names1.split("\\w{1,}");
print(nameArrs1);
}
public static void print(String[] str) {
for (int i = 0; i < str.length; i++) {
System.out.println(str[i]);
}
}
}
```
## 6.8 String類的replaceAll方法中使用正則表示式
- String類的replaceAll()方法原型:
```java
public String replaceAll(String regex,String newStr)//引數regex就是一個正則表示式。可以將當前字串中匹配regex正則表示式的字串替換為newStr。
```
- 程式碼示例:
```java
public class Demo {
public static void main(String[] args) {
//將下面字串中的"數字"替換為"*"
String str = "jfdk432jfdk2jk24354j47jk5l31324";
System.out.println(str.replaceAll("\\d+", "*"));
}
}
```
## 6.9 正則表示式實際案例
```java
// 校驗郵箱
public static void checkEmail() {
Scanner sc = new Scanner(System.in);
System.out.print("請輸入您的郵箱:");
String email = sc.nextLine();
// [email protected]
// [email protected]
// [email protected]
if (email.matches("\\w{1,}@\\w{2,10}(\\.\\w{2,10}){1,2}")) {
System.out.println("郵箱驗證正確!");
} else {
System.err.println("郵箱格式不合法!");
}
}
// 驗證手機號碼
public static void checkPhone() {
Scanner sc = new Scanner(System.in);
System.out.print("請輸入您的手機號碼:");
String phone = sc.nextLine();
// 第一個數字時1,第二個數字時3-9
if(phone.matches("1[3-9]\\d{9}")) {
System.out.println("手機號碼驗證正確!");
} else {
System.err.println("手機號碼格式錯誤!");
}
}
```
```java
/**
在文章中爬取電話號碼和郵箱
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo5 {
public static void main(String[] args) {
String rs = "歡迎致電南京郵電大學,電話020-43433424,或者聯絡郵箱" +
"[email protected],電話18762826338,0223232323" +
"郵箱[email protected],400-100-3233,4001003232";
// 從上面爬取出電話號碼和郵箱
// 1、定義爬取規則(郵箱 || 手機號 || 電話號碼1 || 電話號碼2)
String regex = "(\\w{1,}@\\w{2,10}(\\.\\w{2,10}){1,2})|(1[3-9]\\d{9})|(0\\d{2,5}-?\\d{5,15})|(400-?\\d{3,8}-?\\d{3,8})";
// 2、編譯表示式成為一個匹配規則物件
Pattern pattern = Pattern.compile(regex);
// 3、通過匹配規則物件得到一個匹配器物件
Matcher matcher = pattern.matcher(rs);
// 4、通過匹配器去內容中爬取資訊
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
```
# 第七章 包裝類
## 7.1 概述
Java提供了兩個型別系統,基本型別與引用型別,使用基本型別在於效率,然而很多情況,會建立物件使用,因為物件可以做更多的功能,如果想要我們的基本型別像物件一樣操作,就可以使用基本型別對應的包裝類,如下:
| 基本型別 | 對應的包裝類(位於java.lang包中) |
| -------- | --------------------------------- |
| byte | Byte |
| short | Short |
| int | **Integer** |
| long | Long |
| float | Float |
| double | Double |
| char | **Character** |
| boolean | Boolean |
## 7.2 Integer類
- Integer類概述
包裝一個物件中的原始型別 int 的值
- Integer類構造方法及靜態方法
| 方法名 | 說明 |
| --------------------------------------- | -------------------------------------- |
| public Integer(int value) | 根據 int 值建立 Integer 物件(過時) |
| public Integer(String s) | 根據 String 值建立 Integer 物件(過時) |
| public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 例項 |
| public static Integer valueOf(String s) | 返回儲存指定String值的 Integer 物件 |
- 示例程式碼
```java
public class IntegerDemo {
public static void main(String[] args) {
//public Integer(int value):根據 int 值建立 Integer 物件(過時)
Integer i1 = new Integer(100);
System.out.println(i1);
//public Integer(String s):根據 String 值建立 Integer 物件(過時)
Integer i2 = new Integer("100");
//Integer i2 = new Integer("abc"); //NumberFormatException
System.out.println(i2);
System.out.println("--------");
//public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 例項
Integer i3 = Integer.valueOf(100);
System.out.println(i3);
//public static Integer valueOf(String s):返回儲存指定String值的Integer物件
Integer i4 = Integer.valueOf("100");
System.out.println(i4);
}
}
```
## 7.3 裝箱與拆箱
基本型別與對應的包裝類物件之間,來回轉換的過程稱為”裝箱“與”拆箱“:
- **裝箱**:從基本型別轉換為對應的包裝類物件。
- **拆箱**:從包裝類物件轉換為對應的基本型別。
用Integer與 int為例:(看懂程式碼即可)
基本數值---->包裝物件
```java
Integer i = new Integer(4);//使用建構函式函式
Integer iii = Integer.valueOf(4);//使用包裝類中的valueOf方法
```
包裝物件---->基本數值
```java
int num = i.intValue();
```
## 7.4 自動裝箱與自動拆箱
由於我們經常要做基本型別與包裝類之間的轉換,從Java 5(JDK 1.5)開始,基本型別與包裝類的裝箱、拆箱動作可以自動完成。例如:
```java
Integer i = 4; // 自動裝箱。相當於Integer i = Integer.valueOf(4);
int c = i; // 自動拆箱
i = i + 5;//等號右邊:將i物件轉成基本數值(自動拆箱) i.intValue() + 5;
//加法運算完成後,再次裝箱,把基本數值轉成物件。
```
> 注意:常規開發Integer與int沒什麼區別,Integer容錯更高
## 7.5 基本型別與字串之間的轉換
### 基本型別轉換為String
- 轉換方式
- 方式一:直接在數字後加一個空字串
- 方式二:通過String類靜態方法valueOf()
- 示例程式碼
```java
public class IntegerDemo {
public static void main(String[] args) {
//int --- String
int number = 100;
//方式1
String s1 = number + "";
System.out.println(s1);
//方式2
//public static String valueOf(int i)
String s2 = String.valueOf(number);
System.out.println(s2);
System.out.println("--------");
}
}
```
### String轉換成基本型別 (重要)
除了Character類之外,其他所有包裝類都具有parseXxx靜態方法可以將字串引數轉換為對應的基本型別:
- `public static byte parseByte(String s)`:將字串引數轉換為對應的byte基本型別。
- `public static short parseShort(String s)`:將字串引數轉換為對應的short基本型別。
- **`public static int parseInt(String s)`:將字串引數轉換為對應的int基本型別。**
- **`public static long parseLong(String s)`:將字串引數轉換為對應的long基本型別。**
- `public static float parseFloat(String s)`:將字串引數轉換為對應的float基本型別。
- `public static double parseDouble(String s)`:將字串引數轉換為對應的double基本型別。
- `public static boolean parseBoolean(String s)`:將字串引數轉換為對應的boolean基本型別。
程式碼使用(僅以Integer類的靜態方法parseXxx為例)如:
- 轉換方式
- 方式一:先將字串數字轉成Integer,再呼叫valueOf()方法
- 方式二:通過Integer靜態方法parseInt()進行轉換
- 示例程式碼
> ```java
> // 只需要記住valueOf()方法,即可將String轉換成其他的資料型別(非常推薦)
> String numStr = "23";
> int numInt = Integer.valueOf(numStr);
>
> String doubleStr = "99.9";
> double doubleDb = Double.valueOf(doubleStr);
>
> ```
```java
public class IntegerDemo {
public static void main(String[] args) {
//String --- int
String s = "100";
//方式1:String --- Integer --- int
Integer i = Integer.valueOf(s);
//public int intValue()
int x = i.intValue();
System.out.println(x);
//方式2
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println(y);
}
}
```
> 注意:如果字串引數的內容無法正確轉換為對應的基本型別,則會丟擲`java.lang.NumberFormatException`異常。
# 第八章 泛型(難點)
## 8.1 泛型概述
在前面學習集合時,我們都知道集合中是可以存放任意物件的,只要把物件儲存集合後,那麼這時他們都會被提升成Object型別。當我們在取出每一個物件,並且進行相應的操作,這時必須採用型別轉換。
大家觀察下面程式碼:
```java
public class GenericDemo {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("abc");
coll.add("itcast");
coll.add(5);//由於集合沒有做任何限定,任何型別都可以給其中存放
Iterator it = coll.iterator();
while(it.hasNext()){
//需要列印每個字串的長度,就要把迭代出來的物件轉成String型別
String str = (String) it.next();
System.out.println(str.length());
}
}
}
```
程式在執行時發生了問題**java.lang.ClassCastException**。 為什麼會發生型別轉換異常呢? 我們來分析下:由於集合中什麼型別的元素都可以儲存。導致取出時強轉引發執行時 ClassCastException。 怎麼來解決這個問題呢? Collection雖然可以儲存各種物件,但實際上通常Collection只儲存同一型別物件。例如都是儲存字串物件。因此在JDK5之後,新增了**泛型**(**Generic**)語法,讓你在設計API時可以指定類或方法支援泛型,這樣我們使用API的時候也變得更為簡潔,並得到了編譯時期的語法檢查。
* **泛型**:可以在類或方法中預支地使用未知的型別。
> tips:一般在建立物件時,將未知的型別確定具體的型別。當沒有指定泛型時,預設型別為Object型別。
## 8.2 使用泛型的好處
上一節只是講解了泛型的引入,那麼泛型帶來了哪些好處呢?
* 將執行時期的ClassCastException,轉移到了編譯時期變成了編譯失敗。
* 避免了型別強轉的麻煩。
通過我們如下程式碼體驗一下:
```java
public class GenericDemo2 {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("abc");
list.add("itcast");
// list.add(5);//當集合明確型別後,存放型別不一致就會編譯報錯
// 集合已經明確具體存放的元素型別,那麼在使用迭代器的時候,迭代器也同樣會知道具體遍歷元素型別
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
//當使用Iterator<String>控制元素型別後,就不需要強轉了。獲取到的元素直接就是String型別
System.out.println(str.length());
}
}
}
```
> tips:泛型是資料型別的一部分,我們將類名與泛型合併一起看做資料型別。
## 8.3 泛型的定義與使用
我們在集合中會大量使用到泛型,這裡來完整地學習泛型知識。
泛型,用來靈活地將資料型別應用到不同的類、方法、介面當中。將資料型別作為引數進行傳遞。
### 定義和使用含有泛型的類
> 泛型類的核心思想:把出現泛型變數的地方全部替換成傳輸的真實資料型別
>
> 類的範型變數用E表示
定義格式:
```
修飾符 class 類名<代表泛型的變數> { }
```
* 泛型變數建議使用`E`,`T`,`K`,`V`
```java
public class GenericDemo {
public static void main(String[] args) {
MyArrayList<String> lists = new MyArrayList<>();
lists.add("123"); // 泛型限制了方法只能新增String型別
System.out.println(lists);
}
}
// 需求:模擬ArrayList集合自定義一個集合MyArrayList集合
class MyArrayList<E> {
private static ArrayList lists = new ArrayList();
public void add(E e) {
lists.add(e);
}
public void remove(E e) {
lists.remove(e);
}
@Override
public String toString() {
return lists.toString();
}
}
```
例如,API中的ArrayList集合:
泛型在定義的時候不具體,使用的時候才變得具體。在使用的時候確定泛型的具體資料型別。
```java
class ArrayList<E>{
public boolean add(E e){ }
public E get(int index){ }
....
}
```
使用泛型: 即什麼時候確定泛型。
**在建立物件的時候確定泛型**
例如,`ArrayList<String> list = new ArrayList<String>();`
此時,變數E的值就是String型別,那麼我們的型別就可以理解為:
```java
class ArrayList<String>{
public boolean add(String e){ }
public String get(int index){ }
...
}
```
再例如,`ArrayList<Integer> list = new ArrayList<Integer>();`
此時,變數E的值就是Integer型別,那麼我們的型別就可以理解為:
```java
class ArrayList<Integer> {
public boolean add(Integer e) { }
public Integer get(int index) { }
...
}
```
### 含有泛型的方法
> 方法範型變數用T表示
定義格式:
```
修飾符 <代表泛型的變數> 返回值型別 方法名(引數){ }
```
例如,
```java
public class MyGenericMethod {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public <MVP> MVP show2(MVP mvp) {
return mvp;
}
}
```
**呼叫方法時,確定泛型的型別**
```java
public class GenericMethodDemo {
public static void main(String[] args) {
// 建立物件
MyGenericMethod mm = new MyGenericMethod();
// 演示看方法提示
mm.show("aaa");
mm.show(123);
mm.show(12.45);
}
}
```
### 含有泛型的介面
定義格式:
```
修飾符 interface介面名<代表泛型的變數> { }
```
例如,
```java
public interface MyGenericInterface<E>{
public abstract void add(E e);
public abstract E getE();
}
```
使用格式:
**1、定義類時確定泛型的型別**
例如
```java
public class MyImp1 implements MyGenericInterface<String> {
@Override
public void add(String e) {
// 省略...
}
@Override
public String getE() {
return null;
}
}
```
此時,泛型E的值就是String型別。
**2、始終不確定泛型的型別,直到建立物件時,確定泛型的型別**
例如
```java
public class MyImp2<E> implements MyGenericInterface<E> {
@Override
public void add(E e) {
// 省略...
}
@Override
public E getE() {
return null;
}
}
```
確定泛型:
```java
/*
* 使用
*/
public class GenericInterface {
public static void main(String[] args) {
MyImp2<String> my = new MyImp2<String>();
my.add("aa");
}
}
```
## 8.4 泛型萬用字元
當使用泛型類或者介面時,傳遞的資料中,泛型型別不確定,可以通過萬用字元<?>表示。但是一旦使用泛型的萬用字元後,只能使用Object類中的共性方法,集合中元素自身方法無法使用。
> 在泛型中用`?`表示接收任意型別(在使用的時候使用,而不是定義的時候)
### 萬用字元基本使用
泛型的萬用字元:**不知道使用什麼型別來接收的時候,此時可以使用?,?表示未知萬用字元。**
此時只能接受資料,不能往該集合中儲存資料。
舉個例子大家理解使用即可:
```java
public static void main(String[] args) {
Collection<Intger> list1 = new ArrayList<Integer>();
getElement(list1);
Collection<String> list2 = new ArrayList<String>();
getElement(list2);
}
public static void getElement(Collection<?> coll){}
// ?代表可以接收任意型別
泛型不存在繼承關係 Collection<Object> list = new ArrayList<String>();這種是錯誤的
```
### 萬用字元高階使用
之前設定泛型的時候,實際上是可以任意設定的,只要是類就可以設定。但是在JAVA的泛型中可以指定一個泛型的**上限**和**下限**。
**泛型的上限**:
* **格式**: `型別名稱 <? extends 類 > 物件名稱`
* **意義**: `只能接收該型別及其子類`
**泛型的下限**:
- **格式**: `型別名稱 <? super 類 > 物件名稱`
- **意義**: `只能接收該型別及其父型別`
比如:現已知Object類,String 類,Number類,Integer類,其中Number是Integer的父類
```java
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement(list1);
getElement(list2);//報錯
getElement(list3);
getElement(list4);//報錯
getElement2(list1);//報錯
getElement2(list2);//報錯
getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此時的泛型?,必須是Number型別或者Number型別的子類
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此時的泛型?,必須是Number型別或者Number型別的父類
public static void getElement2(Collection<? super Number> coll){}
```
# 第九章 Collection集合
## 9.1 集合概述
在前面基礎班我們已經學習過並使用過集合ArrayList<E> ,那麼集合到底是什麼呢?
* **集合**:集合是java中提供的一種容器,可以用來儲存多個數據。
集合和陣列既然都是容器,它們有什麼區別呢?
* 陣列的長度是固定的。集合的長度是可變的。
* 陣列中儲存的是同一型別的元素,可以儲存任意型別資料。集合儲存的都是引用資料型別。如果想儲存基本型別資料需要儲存對應的包裝型別。
## 9.2 集合常用類的繼承體系
Collection:單列集合類的根介面,用於儲存一系列符合某種規則的元素,它有兩個重要的子介面,分別是`java.util.List`和`java.util.Set`。其中,`List`的特點是元素有序、元素可重複。`Set`的特點是元素不可重複。`List`介面的主要實現類有`java.util.ArrayList`和`java.util.LinkedList`,`Set`介面的主要實現類有`java.util.HashSet`和`java.util.LinkedHashSet`。
從上面的描述可以看出JDK中提供了豐富的集合類庫,為了便於初學者進行系統地學習,接下來通過一張圖來描述集合常用類的繼承體系
![](https://s1.ax1x.com/2020/09/27/0FElqJ.jpg)
注意:這張圖只是我們常用的集合有這些,不是說就只有這些集合。
集合本身是一個工具,它存放在java.util包中。在`Collection`介面定義著單列集合框架中最最共性的內容。
## 9.3 Collection 常用API
Collection是所有單列集合的父介面,因此在Collection中定義了單列集合(List和Set)通用的一些方法,這些方法可用於操作所有的單列集合。方法如下:
* `public boolean add(E e)`: 把給定的物件新增到當前集合中 。
* `public void clear()` :清空集合中所有的元素。
* `public boolean remove(E e)`: 把給定的物件在當前集合中刪除。
* `public boolean contains(Object obj)`: 判斷當前集合中是否包含給定的物件。
* `public boolean isEmpty()`: 判斷當前集合是否為空。
* `public int size()`: 返回集合中元素的個數。
* `public Object[] toArray()`: 把集合中的元素,儲存到陣列中
> tips: 有關Collection中的方法可不止上面這些,其他方法可以自行檢視API學習。
```java
public class CollectionDemo {
public static void main(String[] args) {
Collection<String> sets = new HashSet<>();
// 新增元素,成功返回true
sets.add("vingkin");
sets.add("趙和月");
// 清空集合元素
// set.clear();
// 判斷集合是否為空,為空true
System.out.println(sets.isEmpty());
// 獲取集合大小
System.out.println(sets.size());
// 判斷集合中是否包含某個元素
System.out.println(sets.contains("vingkin"));
// 刪除某個元素:預設刪除前面的第一個
sets.remove("vingkin");
// 把集合轉換成陣列
Object[] arrs = sets.toArray();
// Arrays.toString()方法是返回陣列內容
System.out.println(Arrays.toString(arrs));
// 直接將Hashset轉換成String型別陣列
String[] arrs1 = sets.toArray(String[]::new); // 轉換成指定的陣列型別
System.out.println(Arrays.toString(arrs1));
}
}
```
集合並集操作
`addAll()`方法