- 最近學習到第 23 天了,還有 4 天時間我的 JavaSE 課程就要結束了,之后會有一個考試,需要復習一下,正好利用這個時間把之前的學習內容給大家總結分享出來。
- 今天分享的內容主要是關于 正則表達式 的幾種功能的使用,還會有一些常用的 API 的使用為大家簡單介紹下,下面就開始我們的學習啦。??
1.正則表達式
1.1 - 正則表達式的概述及簡單使用
- 概述:是指一個用來描述或者匹配一系列符合某個語法規則的字符串的單個字符串。其實就是一個用來表示匹配規則的一個字符串,java 會將這些字符串編譯成執行代碼去做各種運算。
- 舉例:郵箱注冊用戶名和密碼的校驗。
- 校驗 QQ 案例
- 要求:必須是 5 - 15 位字符,0 不能開頭,全部是數字。
- 使用正則表達式判斷:
[1-9]\\d{4,14}
。
這里舉這個小栗子??是為了讓大家可以看到,使用了正則表達式的判斷是非常的方便的,稍后會為大家介紹這個正則表達式的意義。
1.2 - 字符類
首先我們先來學習以下正則表達式中的字符類,我們想要對一個字符串中的各個字符進行判斷,就要知道每個字符在正則表達式中的表示規則,知道了這個之后我們就能繼續向下學習了。
Character classes
[abc]
a, b, or c (simple class)
[^abc]
Any character except a, b, or c (negation)
[a-zA-Z]
a through z or A through Z, inclusive (range)
[a-d[m-p]]
a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]]
d, e, or f (intersection)
[a-z&&[^bc]]
a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]]
a through z, and not m through p: [a-lq-z] (subtraction)
-
[ ]
: 代表單個字符。
-
[^]
: 除了該字符外的所有單個字符。
-
[a-zA-Z]
: [a-z] || [A-Z]。
-
[a-d[m-p]]
:[a, d] || [m, p] 并集關系。
-
[a-z&&[def]]
:交集 {“d”, “e”, “f”}。
-
[a-z&&[^bc]]
:a-z && [^bc],a-z 除去 bc。
-
[a-z&&[^m-p]]
:a-z 中除了 m-p。
Reminder ???♂?
[ ] 中括號中的內容我們可以理解為,對于一個單個的字符中,可以包含的字符的一個集合。
1.3 - 預定義字符類
預定義字符相當于正則表達式中,為我們提供了一些特殊的字符集合的快捷表達方式。學習了這個字符類之后,就可以用一個簡單字符表達一個特殊的字符集合了。
redefined character classes
.
Any character (may or may not match line terminators)
\d
A digit: [0-9]
\D
A non-digit: [^0-9]
\h
A horizontal whitespace character:[ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]
\H
A non-horizontal whitespace character: [^\h]
\s
A whitespace character: [ \t\n\x0B\f\r]
\S
A non-whitespace character: [^\s]
\v
A vertical whitespace character: [\n\x0B\f\r\x85\u2028\u2029]
\V
A non-vertical whitespace character: [^\v]
\w
A word character: [a-zA-Z_0-9]
\W
A non-word character: [^\w]
-
.
:任意字符。
-
\d
:[0-9] 單個數字字符。
\d 代表轉義字符,如果想表示 \d 的話,需要 \d。
-
\D
:[^0-9] 除了數字外的單個字符。
-
\s
:[\t\n\x0B\f\r] 空白字符。
-
\S
:[^\s] 非空白字符。
-
\w
:[a-zA-Z_0-9] 單詞字符。
下劃線也屬于單詞字符。
-
\W
:[^\w] 非單詞字符。
1.4 - 數量詞
上面我們學習了各種字符及字符集在正則表達式中的表達方式,但是如果我們想要表達一個字符出現多次時,我們就需要借助與正則表達式的另外一個規則了,這個規則就是數量詞。
quantifiers
X?
X, once or not at all
X*
X, zero or more times
X+
X, one or more times
X{n}
X, exactly n times
X{n,}
X, at least n times
X{n, m}
X, at least n but not more than m times
-
X?
:出現 1 次 或 1 次也沒有(不能出現其他)。
-
X*
:出現 0 次 或 更多次。
-
X+
:出現 1 次 或 多次,不包括 0 次。
-
X{n}
:出現恰好 n 次。
-
X{n,}
:出現至少 n 次。
-
X{n,m}
:出現 [n, m] 次,包含 n 也包含 m。
1.5 - 分割功能
下面介紹一個 String 類中的方法,它的參數是 regex
也就是我們今天學習的正則表達式,那么我們來簡單使用一下吧。
- public String[] split(String regex)
- 概述:字符串分割方法,將給定字符串中,兩端都符合正則表達式的字符串拆分出來。特別的,這個匹配的字符串不會出現在返回的字符數組中。
- 案例:我們有一個已知的字符串,其中包含了多個名字,并且每個名字中間都用
,
分隔,我們想要獲取每個名字,此時可以借助正則表達式來完成。
String str = "Sawyer,Jerry,Tom";
String[] arr_str = str.split("\\,”);
System.out.println(Arrays.toString(arr_str));
Reminder ???♂?
這里的正則表達式需要寫成 \\\,
,表示是正則表達式的 \\,
如果寫成 \\,
則代表的是字符中的轉義字符。
1.6 - 替換功能
- public String replaceAll(String regex, String replacement)
- 正則表達式替換功能。
String str1 = “I123 Love432 Sa324wyer!”; // 去掉數字
// 任意數字,使用 + 可以匹配多位數字,減少 replace 次數,提高性能。
String reget = “\\d+”;
String str2 = str1.replaceAll(reget, “”);
System.out.println(str2);
- 這里我們借助 String 中的另一個方法
replaceAll()
方法將字符串中的所有數字替換為空字符串。特別的,這里的正則表達式中使用了 +
來匹配出現 1 次或多次的數字,也就是將一組連續的數字一次替換掉,而不需要每次只替換掉一個數字,提高性能。
1.7 - 分組功能
- 概述:捕獲組可以通過從左到右計算其開括號來進行編組。類似數學中的 () 將多次出現的字符串歸為一組。
讀讀 API ??
Capturing groups are numbered by counting their opening parentheses from left to right. In the expression ((A)(B(C))), for example, there are four such groups:
1 ((A)(B(C)))
2 (A)
3 (B(C))
4 (C)
/*
(.)代表任意一組字符
\\1 代表一組再次出現一次
\\2 代表第二組又出現了一次
*/
String regex1 = "(.)\\1(.)\\2";
System.out.println("快快樂樂".matches(regex1)); // true
System.out.println("快樂樂樂".matches(regex1)); // false
System.out.println("高高興興".matches(regex1)); // true
System.out.println("死啦死啦".matches(regex1)); // false
String regex2 = "(..)\\1";
System.out.println("死啦死啦".matches(regex2)); // true
System.out.println("高興高興".matches(regex2)); // true
System.out.println("快快樂樂".matches(regex2)); // false
- 需求:請按照疊詞切割:"sdqqfgkkkhjppppk1";
String str_sou = "sdqqfgkkkhjppppk1";
// 將出現 1 次或多次的字符組切掉,+ 代表1組出現一次或多次。
String regex = "(.)\\1+";
String[] arr_str = str_sou.split(regex);
System.out.println(Arrays.toString(arr_str));
- 需求:”我我....我...我.要...要要要...要學....學學..學.編..編編.編.程.程.程..程”,將字符串還原成:"我要學編程"。
String str_sou = "我我....我...我.要...要要要...要學....學學..學.編..編編.編.程.程.程..程";
// 1.去掉.
String regex_replace1 = "\\.+";
String str_replace1 = str_sou.replaceAll(regex_replace1, "");
System.out.println(str_replace1);
// 2.替換組
String regex_replace2 = "(.)\\1+";
// $1 代表第一組中內容,()內的內容。
String str_replace2 = str_replace1.replaceAll(regex_replace2, "$1");
System.out.println(str_replace2);
2.Pattern 和 Matcher
2.1 - Pattern 概述
- 一個正則表達式字符串,必須首先成一個 Pattern 實例對象,用于對正則表達式字符串進行編譯。生成的對象可以用于創建 Matcher 對象,可以匹配任意字符序列。
所有執行狀態的匹配都保存在匹配器中,這些匹配器可以被共享。
讀讀 API ??
A regular expression, specified as a string, must first be compiled into an instance of this class. The resulting pattern can then be used to create a Matcher object that can match arbitrary character sequences against the regular expression. All of the state involved in performing a match resides in the matcher, so many matchers can share the same pattern.
// 編譯正則表達式
Pattern p = Pattern.compile("a*b");
// 獲取匹配器
Matcher m = p.matcher("aaaaab");
// 執行匹配
boolean b = m.matches();
- 不建議將它用在單次調用中,該語句雖然等效與上面三個語句,但是重復匹配的效率低,因為每次都要通過 Pattern 編譯正則表達式語句。
boolean b = Pattern.matches("a*b", "aaaaab");
讀讀 API ??
A matches method is defined by this class as a convenience for when a regular expression is used just once. This method compiles an expression and matches an input sequence against it in a single invocation. The statement
is equivalent to the three statements above, though for repeated matches it is less efficient since it does not allow the compiled pattern to be reused.
- Pattern 的實例是不可變的,在多線程是安全的。但這樣使用 Matcher 類的實例是不安全的。
Instances of this class are immutable and are safe for use by multiple concurrent threads. Instances of the Matcher class are not safe for such use.
- API 總結
- Pattern 用于編譯正則表達式。
- Matcher 用于創建匹器,匹配器可以匹配任意字符序列,并且可以執行多個匹配任務。
- 典型的執行順序:編譯正則表達式 -> 創建匹配器 -> 執行匹配
- 如果需要用同一個正則表達式來匹配多個字符序列時,建議重復使用同一個 Pattern 編譯器對象。
- Pattern 的實例是不可變并且線程安全的,但是 Matcher 實例是線程不安全的。
2.2 - Pattern 應用
- 需求:將一個字符串中的手機號碼獲取出來。
- 數據:"我的手機號是18676403416,曾經用過13364286497,還用過18988888888";
String str_sou = "我的手機號是18676403416,曾經用過13364286497,還用過18988888888";
// 手機號的正則表達式
String REGEX_NUM = "1[3578]\\d{9}";
Pattern p = Pattern.compile(REGEX_NUM);
Matcher m = p.matcher(str_sou);
boolean b = m.find(); // 嘗試查找與該匹配模式所匹配的下一個子序列
System.out.println(b);
// No match found 需要先執行 find() 后再獲取
String str_group = m.group(); // 獲取曾經查找到的子序列
System.out.println(str_group);
/*
* 正則匹配器的典型應用
* 遍歷 find() 方法 獲取所有 group() 子串
* */
while (m.find())
System.out.println(m.group());
3.Math
- 概述
Math 是一個 final 修飾的類,所有成員都是靜態的,并且私有構造方法不能被實例化。
public final class Math
- 成員變量
public static final double PI
The double value that is closer than any other to pi, the ratio of the circumference of a circle to its diameter.
13.0 -12
12.3 -12.99
12.0 -13
-
public static double floor(double a)
ceil(地板),向下(數值小)取整,結果是 double 類型。
13.0 -12
12.3 -12.99
12.0 -13
public static int max(int a, int b)
獲取兩個值中的最大值。
public static double pow(double a, double b)
乘方運算:a 是底數,b 是指數。
public static double random()
生成 [0.0, 1.0) 隨機數。
public static int round(float a)
四舍五入:參數是 float 類型時返回 int 類型,參數是 double 類型時返回 long 類型。
public static double sqrt(double a)
開平方根:返回 double 類型。
4.Random
- 構造方法一
使用 System.nanoTime() 納秒值作為種子。
Random random1 = new Random();
for (int i = 0; i < 10; i++) {
System.out.println(random1.nextInt());
}
- 構造方法二
相同的種子時,同一次調用 nextInt 的結果是一樣的,換句話說,每運行得到的 a b 結果是固定的。
Random random2 = new Random(1000);
int a = random2.nextInt();
int b = random2.nextInt();
System.out.println(a);
System.out.println(b);
public int nextInt(int n)
取值范圍 [0, bound) 等價于 [0, bound - 1]
?? 取值范圍[0, 100) => [0, 99]
System.out.println(random1.nextInt(100));
5.System
5.1 - 概述
System 類包含幾個有用的類字段和方法。它不能被實例化。
讀讀 API ??
The System class contains several useful class fields and methods. It cannot be instantiated.
5.2 - 標準輸入輸出流。
1. In:標準輸入流,默認指向鍵盤。
2. Out:標準輸出流,默認指向控制臺。
5.3 - 靜態方法:
-
public static void gc()
執行垃圾回收器。
class FinalizeTest {
// 當 FinalizeTest 類的對象變成垃圾對象后,回收器在不確定時間回收這個對象。
// 在回收之前,會調用這個方法。
@Override
protected void finalize() throws Throwable {
System.out.println("Garbage is cleared!");
}
}
public static void exit(int status)
立刻退出 JVM 運行,按照慣例,非 0 狀態表示異常終止。
public static long currentTimeMillis()
1970 UTC 至今毫秒 milliseconds,可以用于計算方法執行時間。
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src - the source array.
srcPos - starting position in the source array.
dest - the destination array.
destPos - starting position in the destination data.
length - the number of array elements to be copied.
- src - 源數組。
- srcPos - 源數組起始位置。
- dest - 目標數組。
- destPos - 目標數組的起始數據。
- length - 要復制的數組元素的數目。
6.BigInteger
- 概述:可以讓超過
Integer
范圍的數進行運算,可以存放任意精度的整數。
例如我們想將這樣一個數賦值給變量。
long l = 12345678987654321123456789
這個數的大小已經超過了 long 的 取值范圍,所以編譯報錯。
我們可以通過 String 字符串來創建 BigInteger 對象來保存這個數值,并進行數學運算。
BigInteger bi1 = new BigInteger("12345678987654321123456789");
igInteger bi1 = new BigInteger("100");
BigInteger bi2 = new BigInteger("2");
System.out.println(bi1.add(bi2)); // +
System.out.println(bi1.subtract(bi2)); // -
System.out.println(bi1.multiply(bi2)); // *
System.out.println(bi1.divide(bi2)); // /
// 取商 取模
BigInteger[] arr_bi = bi1.divideAndRemainder(bi2);
System.out.println(Arrays.toString(arr_bi));
7.BigDecimal
BigDecimal bd1 = new BigDecimal(2.0);
BigDecimal bd2 = new BigDecimal(1.1);
System.out.println(bd1.subtract(bd2)); // 0.899999999999999911182158029987476766109466552734375
- 方式二:推薦方式??通過構造方法中傳入字符串的方式。
BigDecimal bd3 = new BigDecimal("2.0");
BigDecimal bd4 = new BigDecimal("1.1");
System.out.println(bd3.subtract(bd4)); // 0.9
BigDecimal bd5 = BigDecimal.valueOf(2.0);
BigDecimal bd6 = BigDecimal.valueOf(1.1);
System.out.println(bd5.subtract(bd6)); // 0.9
8.Date (java.util.Date)
8.1 - 概述
分配 Date 對象并初始化它自從標準基準時間,稱為"新紀元",即 1970 年 1 月 1 日,格林尼治標準時間 00:00:00 代表指定的毫秒數。
讀讀 API ??
Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
8.2 - 構造方法
8.3 - 成員方法
-
public long getTime()
將時間轉換為毫秒值。
兩個取值方式是相同的。
new Date().getTime() // 通過事件對象獲取毫秒值。
System.currentTimeMillis() // 通過系統方法獲取毫秒值。
-
public void setTime(long time)
設置毫秒值,改變時間對象,1000毫秒 = 1秒。
9.SimpleDataFormat
// 方式一:默認格式
Date date = new Date();
SimpleDateFormat sdf1 = new SimpleDateFormat();
System.out.println(sdf1.format(date));
// 方式二:自定義格式
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));
String str = "2016年12月22日 08:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = sdf.parse(str); // 解析出 Date
System.out.println(sdf.format(d));
10.Test?????你來到這個世界多少天?
- 需求:計算你來到這個世界多少天?
- 分析
- 將生日字符串和今天字符串對象存儲在 String 類型的變量中
- 定義日期格式化對象
- 將日期字符串轉換成日期對象
- 通過日期對象計算出時間差值
- 將時間毫秒值轉換為天數
public class Test {
public static void test() throws ParseException {
// 1.將日期存儲在 String 變量中
String str_birthday = "1991 年 10 月 21 日";
String str_today = "2016 年 11 月 22 日";
// 2.定義日期格式化對象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日");
// 3.將日期字符串轉換為日期對象
Date date_birthday = sdf.parse(str_birthday);
Date date_today = sdf.parse(str_today);
// 4.通過日期對象計算毫秒值
long time = date_today.getTime() - date_birthday.getTime();
// 5.轉換為天數
System.out.println(time / 1000 / 60 / 60 / 24);
}
}
11.Calendar
概述:是一個抽象類,子類有 GregorianCalendar。
public static Calendar getInstance()
父類引用指向子類對象:可以使用子類中的重寫方法。
public int get(int field)
Field Detail。
Reminder ???♂?
月份:[0, 11]
星期:從周日開始。
abstract public void add(int field, int amount)
對日歷中元素進行加減操作。
public final void set(int year, int month, int date)
設置年月日。
Reminder ???♂?
12 -> 0 年 進位 -> 2017
悄悄話 ??
- 已經有一段時間沒有和小伙伴們分享我的學習筆記了,接下來的幾天我會把我之前的筆記都整理并陸續的分享出來。
- 和小伙伴們匯報下我最近的學習情況吧,今天完成了又一個階段的學習,剛剛結束了 IO 流的考試,考試成績很不錯??(開心),今天是休息日,因為馬上 JavaSE 的課程就要結束了,感覺班級的學習氛圍有些不如以前,本該是抓緊復習的時候,但是明顯感覺一部分的人已經開始浮躁起來了。我個人還好,已經做好了復習的計劃正在有條不紊的進行著。
- 因為馬上就要放假了,大概有20天的時間,今天過年打算留在魔都不回家過年了,所以我要計劃一下趁著放假的時間啃一本書才好,列了一下要看的書單,其中有《深入理解JVM虛擬機》 《Java并發編程實戰》 《Effective Java》 《軟件建模與設計》。本著我自己的想法,我是想按照這3本的順序依次往下啃的,可開學之后就要進入 JavaEE 的學習了,老師的建議是先自學一下 JS 以及一些前端的技術,之前接觸過一些前端的技術,但都是懵懂狀態,想著學習了 Java 并且今后是要伴隨終生的一門語言,應該要深挖一下這門語言的一些底層實現,不然的話遇到一些深入的問題根本無從下手去解決,很不喜歡這樣的狀態。所以如果有在做 JavaEE 開發的小伙伴也可以給我提一些建議,我就感激不盡了。
- 好了,寫了這么多,只是想與大家交流一下,而不只是把技術性的東西貼在這里作為展示,能一起交流探討一下才是最重要的。我要繼續整理接下來的筆記了,想要交流的小伙伴們可以評論或發私信給我。
彩蛋 ??
-
最近開通了簡書專題 JavaSE 成長之路,主要為一樣正在 JavaSE 修行中的簡友們提供了技術交流的平臺,希望大家多多投稿交流互動。
如果你覺得我的分享對你有幫助的話,請在下面??隨手點個喜歡 ??,你的肯定才是我最大的動力,感謝。