第3章 - Java 數(shù)組 和 字符串
作者:vwFisher
時(shí)間:2019-09-04
GitHub代碼:https://github.com/vwFisher/JavaBasicGuide
目錄
1 數(shù)組
(basic.array.ArrayDemo)
概念: 同一種數(shù)據(jù)類型的數(shù)據(jù)集合, 其實(shí)數(shù)組就是一個(gè)容器
好處: 可以自動(dòng)給數(shù)組中的元素從0開始編號(hào), 方便操作這些元素
說明: 數(shù)組作為對(duì)象允許使用new關(guān)鍵字進(jìn)行內(nèi)存分配, 在使用數(shù)組之前, 必須首先聲明數(shù)組變量所屬的類型
1.1 一維數(shù)組
概念: 一組相同類型數(shù)據(jù)的集合
語法:
1).數(shù)組元素類型 數(shù)組名字[] = new 數(shù)組元素類型[數(shù)組元素個(gè)數(shù)]
2).數(shù)組元素類型[] 數(shù)組名字 = new 數(shù)組元素類型[數(shù)組元素個(gè)數(shù)]
3).數(shù)組元素類型[] 數(shù)組名 = new 元素類型[]{元素, 元素, ...};
4).數(shù)組元素類型[] 數(shù)組名 = {元素, 元素, ...};
int arr[] = new int[5];
int[] arr = new int[5];
// 定義并初始化
int[] arr = new int[]{3, 5, 1, 7};
int[] arr = {3, 5, 1, 7};
說明:
- 數(shù)組元素類型: 決定數(shù)組的數(shù)據(jù)類型(Java任意數(shù)據(jù)類型)
- 數(shù)組名字: 合法的標(biāo)識(shí)符
- 符號(hào)"[]": 指明該變量是一個(gè)數(shù)組類型變量, 單個(gè)"[]"表示要?jiǎng)?chuàng)建的數(shù)組是一維數(shù)組
- new: 對(duì)數(shù)組分配空間的關(guān)鍵字(因?yàn)閿?shù)組是作為對(duì)象允許使用new關(guān)鍵字進(jìn)行內(nèi)存分配的, 使用new關(guān)鍵字時(shí)候, 整數(shù)類型默認(rèn)初始化值為0)
- 數(shù)組元素的個(gè)數(shù): 指定數(shù)組中變量的個(gè)數(shù), 即數(shù)組的長度
一維數(shù)組運(yùn)行內(nèi)存例子
(basic.demo08.MemoryDiagram1)
public static void main(String[] args) {
int[] arr = new int[3];
arr[0] = 89;
int[] arr2 = arr;
System.out.println(arr[0]);
arr = null;
}
圖示說明:
- 主方法main先壓棧
- int[] arr: arr壓棧
- new int[3]: 放在堆里, 通過new關(guān)鍵字在堆中開辟空間, 內(nèi)存在存儲(chǔ)數(shù)據(jù)的時(shí)候會(huì)開辟內(nèi)存地址(例: 0x0045(16進(jìn)制)的地址空間, 數(shù)組有腳標(biāo), 劃分3個(gè)格子, 每個(gè)格子有對(duì)應(yīng)的下標(biāo)標(biāo)號(hào), 并默認(rèn)初始化設(shè)置為0)
- 然后對(duì)應(yīng)arr地址就是0x0045, arr就指向該地址的對(duì)象數(shù)組(這種就叫做引用數(shù)據(jù)類型(C就叫指針))
- 修改arr指向地址中的下標(biāo)0的值為89
- 此處不難理解, 當(dāng)定義int[] arr2 = arr, 實(shí)際上就是將arr的指向地址賦給arr2
- 找到arr指向地址中的下標(biāo)0的值顯示
- 當(dāng)想取消arr的指向, 賦值arr=null
- arr=null之后, Java自動(dòng)回收機(jī)制會(huì)不定時(shí)的回收垃圾數(shù)據(jù)
1.2 二維數(shù)組(多維數(shù)組同理)
概念: 如果一維數(shù)組中的各個(gè)元素仍然是一維數(shù)組, 那么它就是一個(gè)二維數(shù)組, 常用于表, 第一個(gè)下標(biāo)代表行, 第二個(gè)下標(biāo)代表列
語法:
1).int arr[][] = new int[2][4];
int[][] arr = new int[2][4];
{1}.定義了名稱為arr的二維數(shù)組
{2}.二維數(shù)組中有2個(gè)一維數(shù)組
{3}.每一個(gè)一維數(shù)組中有4個(gè)元素
{4}.一維數(shù)組的名稱分別為arr[0], arr[1]
{5}.給第一個(gè)一維數(shù)組1腳標(biāo)位賦值位78寫法是: arr[0][1] = 78
2).int arr[][] = new int[2][];
int[][] arr = new int[2][];
{1}.二維數(shù)組中有3個(gè)一維數(shù)組
{2}.每個(gè)一維數(shù)組都是默認(rèn)初始化值null
{3}.可以對(duì)這個(gè)三個(gè)一維數(shù)組分別進(jìn)行初始化
arr[0] = new int[2]; arr[1] = new int[3];
3).int[][] arr = {{3, 1, 7}, {5, 8, 2, 9}, {4, 1}}
二維數(shù)組運(yùn)行內(nèi)存例子
(basic.array.MemoryDiagram2)
public static void main(String[] args) {
int[][] arr = new int[3][2];
arr[1][1] = 89;
arr[2][2] = 89; // error
// 分別對(duì)二維數(shù)組中的每一個(gè)小數(shù)組進(jìn)行初始化
int[][] arr2 = new int[3][];
arr2[0] = new int[2];
arr2[1] = new int[1];
arr2[2] = new int[3];
}
圖示說明:
- 主方法main先壓棧
- int[][] arr: arr壓棧
- new int[3][2]:進(jìn)堆, 通過new關(guān)鍵字在堆中開辟空間, 如圖, 創(chuàng)建地址0x0034指向賦給arr, 然后因?yàn)槎S數(shù)組中就是小地址, 再開辟3個(gè)地址, 對(duì)應(yīng)就是小數(shù)組的地址
- arr[1][1]=89, 就是先找0x0034, 在找到下標(biāo)1, 即地址0x0089的下標(biāo)1賦值88
- arr[2][2]=89, 找到0x0034, 在找0x0012, 但是不存在下標(biāo)2的對(duì)應(yīng)位置, 所以這段代碼報(bào)錯(cuò)
1.3 數(shù)組-常見操作(詳細(xì)見程序的demo)
(basic.array.ArrayDemo)
嘗試自己實(shí)現(xiàn)功能:遍歷數(shù)組们童,獲取數(shù)組最大/小值政勃,基本下標(biāo)查找
1.3.3 選擇排序(SelectSort)
每一趟從待排序的數(shù)據(jù)元素中選出最小(或最大)的一個(gè)元素, 順序放在已排好序的數(shù)列的最后, 直到全部待排序的數(shù)據(jù)元素排完背稼。
選擇排序是不穩(wěn)定的排序方法, n個(gè)記錄的文件的直接選擇排序可經(jīng)過n-1趟直接選擇排序得到有序結(jié)果
1.3.4 冒泡排序(BubbleSort)
冒泡排序是交換排序中一種簡單的排序方法. 它的基本思想是對(duì)所有相鄰記錄的關(guān)鍵字值進(jìn)行比效, 如果是逆順(a[j]>a[j+1]), 則將其交換, 最終達(dá)到有序化. 其處理過程為:
- 將整個(gè)待排序的記錄序列劃分成有序區(qū)和無序區(qū), 初始狀態(tài)有序區(qū)為空, 無序區(qū)包括所有待排序記錄
- 對(duì)無序區(qū)從前向后依次將相鄰記錄的關(guān)鍵字進(jìn)行比較, 若逆序?qū)⑵浣粨Q, 從而使得關(guān)鍵字值小的記錄向上"飄浮"(左移), 關(guān)鍵字值大的記錄好像石塊, 向下"墮落"(右移)
每經(jīng)過一趟冒泡排序, 都使無序區(qū)中關(guān)鍵字值最大的記錄進(jìn)入有序區(qū), 對(duì)于n個(gè)記錄組成的記錄序列, 最多經(jīng)過n-1趟冒泡排序, 就可以將這n個(gè)記錄重新按關(guān)鍵字順序排列
【注: 想象輕(小)的浮在上面(左), 重(大)的落在下面(右)】
1.3.6 折半查找(二分查找 HalfSearch)
優(yōu)點(diǎn): 比較次數(shù)少, 查找速度快, 平均性能好
缺點(diǎn): 要求待查表為有序表, 且插入刪除困難
場景: 不經(jīng)常變動(dòng)而查找頻繁的有序列表
折半查找法也稱為二分查找法, 它充分利用了元素間的次序關(guān)系, 采用分治策略, 可在最壞的情況下用O(log n)完成搜索任務(wù).
它的基本思想是, 將n個(gè)元素分成個(gè)數(shù)大致相同的兩半, 取a[n/2]與欲查找的x作比較, 如果x=a[n/2]則找到x, 算法終止. 如果x<a[n/2], 則我們只要在數(shù)組a的左半部繼續(xù)搜索x(這里假設(shè)數(shù)組元素呈升序排列). 如果x>a[n/2], 則我們只要在數(shù)組a的右半部繼續(xù)搜索x
1.4 byte數(shù)組的一些使用
1.4.1 byte數(shù)組的編解碼
(basic.array.EncodeDemo)
private static String ENCODING_GBK = "GBK";
private static String ENCODING_UTF8 = "UTF-8";
public static void main(String[] args) throws IOException {
String str = "謝謝";
byte[] encodeGbkByte = encodeDemo(str, ENCODING_GBK);
printBytes(encodeGbkByte);
String decodeUtf8 = decodeDemo(encodeGbkByte, ENCODING_UTF8);
System.out.println(decodeUtf8);
byte[] encodeUtf8Byte = encodeDemo(decodeUtf8, ENCODING_UTF8);
printBytes(encodeUtf8Byte);
String decodeGbk = decodeDemo(encodeUtf8Byte, ENCODING_GBK);
System.out.println(decodeGbk);
}
private static byte[] encodeDemo(String str, String charset) {
try {
return str.getBytes(charset);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
private static String decodeDemo(byte[] byteArray, String charset) {
try {
return new String(byteArray, charset);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
private static void printBytes(byte[] buf) {
for (byte b : buf) {
System.out.print(b + " ");
}
System.out.println();
}
1.5 Arrays(數(shù)組工具類)
(basic.demo08.ArraysDemo)
此類包含用來操作數(shù)組(比如排序和搜索)的各種方法. 還包含一個(gè)允許將數(shù)組作為列表來查看的靜態(tài)工廠.
除非特別注明, 否則如果指定數(shù)組引用為 null, 則此類中的方法都會(huì)拋出 NullPointerException.
Arrays常用工具類方法歸類:大部分方法都含有基礎(chǔ)數(shù)據(jù)的參數(shù)宫纬,以下省略說明:
- typeAll:byte、short万俗、int湾笛、long、float闰歪、double嚎研、char、Object
- typeBasic:byte库倘、short济舆、int诅迷、long球化、float齐鲤、double、char
1).排序
void sort(typeAll[] a) // 對(duì)指定Object型數(shù)組按升序排序
void sort(Object[] a, int fromIndex, int toIndex) // 指定范圍排序
<T> void sort(T[] a, Comparator<? super T> c) // 指定比較器順序排序
<T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
void parallelSort(typeBasic[] a) // 并行排序
void parallelSort(typeBasic[] a, int fromIndex, int toIndex)
<T extends Comparable<? super T>> void parallelSort(T[] a)
<T extends Comparable<? super T>> void parallelSort(T[] a, int fromIndex, int toIndex)
<T> void parallelSort(T[] a, Comparator<? super T> cmp) // 指定比較器順序并行排序
<T> void parallelSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> cmp)
2).搜索
int binarySearch(typeAll[] a, typeAll key) // 使用二分搜索法來搜索指定的下標(biāo)值
int binarySearch(typeAll[] a, int fromIndex, int toIndex, typeAll key)
<T> int binarySearch(T[] a, T key, Comparator<? super T> c)
<T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
3).比較
boolean equals(typeAll[] a, typeAll [] a2) // 如果兩個(gè)指定的數(shù)組彼此相等饱亿,則返回 true
4).賦值
void fill(typeAll[] a, typeAll val) // 將指定的值賦值給數(shù)組所有元素
void fill(typeAll[] a, int fromIndex, int toIndex, typeAll val)
5).復(fù)制
<T> T[] copyOf(T[] original, int newLength) 復(fù)制指定的數(shù)組, 截取或用null填充(如有必要), 以使副本具有指定的長度
<T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) 復(fù)制指定的數(shù)組, 截取或用null填充(如有必要), 以使副本具有指定的長度
<T> T[] copyOfRange(T[] original, int from, int to) 將指定數(shù)組的指定范圍復(fù)制到一個(gè)新數(shù)組
<T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType)
typeBasic[] copyOf(typeBasic[] original, int newLength) // 復(fù)制指定的數(shù)組, 截取或用0[注:boolean用false, char用null, 其余用0]填充(如有必要), 以使副本具有指定的長度
typeBasic[] copyOf(typeBasic[] original, int from, int to)
6).Array -> List
<T> List<T> asList(T... a) // 返回一個(gè)受指定數(shù)組支持的固定大小的列表
7).獲取
int hashCode(typeAll[] a) // 基于指定數(shù)組的內(nèi)容返回哈希碼
int deepHashCode(Object a[]) // 基于指定數(shù)組的"深層內(nèi)容"返回哈希碼
boolean deepEquals(Object[] a1, Object[] a2) // 如果兩個(gè)指定數(shù)組彼此是深層相等的, 則返回true
String toString(typeAll[] a) // 返回指定數(shù)組內(nèi)容的字符串表示形式
String deepToString(Object[] a) 返回指定數(shù)組"深層內(nèi)容"的字符串表示形式
8).其他
<T> void legacyMergeSort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
<T> void parallelPrefix(T[] array, BinaryOperator<T> op)
<T> void parallelPrefix(T[] array, int fromIndex, int toIndex, BinaryOperator<T> op)
void parallelPrefix(long[] array, LongBinaryOperator op)
void parallelPrefix(long[] array, int fromIndex, int toIndex, LongBinaryOperator op)
void parallelPrefix(double[] array, DoubleBinaryOperator op)
void parallelPrefix(double[] array, int fromIndex, int toIndex, DoubleBinaryOperator op)
void parallelPrefix(int[] array, IntBinaryOperator op)
void parallelPrefix(int[] array, int fromIndex, int toIndex, IntBinaryOperator op)
<T> void setAll(T[] array, IntFunction<? extends T> generator)
<T> void parallelSetAll(T[] array, IntFunction<? extends T> generator)
void setAll(int[] array, IntUnaryOperator generator)
void parallelSetAll(long[] array, IntToLongFunction generator)
void setAll(double[] array, IntToDoubleFunction generator)
void parallelSetAll(double[] array, IntToDoubleFunction generator)
<T> Spliterator<T> spliterator(T[] array)
<T> Spliterator<T> spliterator(T[] array, int startInclusive, int endExclusive)
Spliterator.OfInt spliterator(int[] array)
Spliterator.OfInt spliterator(int[] array, int startInclusive, int endExclusive)
Spliterator.OfLong spliterator(long[] array)
Spliterator.OfLong spliterator(long[] array, int startInclusive, int endExclusive)
Spliterator.OfDouble spliterator(double[] array)
Spliterator.OfDouble spliterator(double[] array, int startInclusive, int endExclusive)
<T> Stream<T> stream(T[] array)
<T> Stream<T> stream(T[] array, int startInclusive, int endExclusive)
IntStream stream(int[] array)
IntStream stream(int[] array, int startInclusive, int endExclusive)
LongStream stream(long[] array)
LongStream stream(long[] array, int startInclusive, int endExclusive)
DoubleStream stream(double[] array)
DoubleStream stream(double[] array, int startInclusive, int endExclusive)
2 字符串
2.1 String類
String類即字符串類型(不可變類), 并不是Java的基本數(shù)據(jù)類型, 但可以像基本數(shù)據(jù)類型一樣使用, 用雙引號(hào)括起來進(jìn)行聲明. 在Java中用String類的構(gòu)造方法來創(chuàng)建字符串變量
特點(diǎn):
- 字符串是一個(gè)特殊的對(duì)象
- 字符串對(duì)象一旦被初始化就不會(huì)被改變, 查看源碼可以看到定義:
public final class String
- 不可變原因蚜退,在 String 類中使用 final 關(guān)鍵字修飾字符數(shù)組來保存字符串:
private final char value[]
2.2 String的方法
(basic.str.StringDemo, StringMethod)
底層實(shí)現(xiàn): char value[]; 用類型是char的數(shù)組來存儲(chǔ)數(shù)據(jù)
String主要方法如下:
1).構(gòu)造函數(shù)
public String() // 初始化一個(gè)新創(chuàng)建的String對(duì)象, 默認(rèn)為:""
public String(String original)
public String(char value[])
public String(char value[], int offset, int count)
public String(int[] codePoints, int offset, int count)
public String(byte bytes[], String charsetName) 使用指定的charset解碼指定的byte數(shù)組
public String(byte bytes[], int offset, int length, String charsetName)
public String(byte bytes[], int offset, int length, Charset charset)
public String(byte bytes[], Charset charset)
public String(byte bytes[], int offset, int length)
public String(byte bytes[])
public String(StringBuffer buffer)
public String(StringBuilder builder)
過時(shí)的構(gòu)造函數(shù):該方法無法將字節(jié)正確地轉(zhuǎn)換為字符.從JDK1.1開始, 完成該轉(zhuǎn)換的首選方法是使用帶有Charset、字符集名稱, 或使用平臺(tái)默認(rèn)字符集的String構(gòu)造方法
public String(byte ascii[], int hibyte, int offset, int count)
public String(byte ascii[], int hibyte)
2).判斷
boolean isEmpty() // 當(dāng)且僅當(dāng)length()為 0 時(shí)返回true
boolean startsWith(String prefix) // 測試此字符串是否以指定的前綴開始
boolean startsWith(String prefix, int toffset) // 同上彪笼,區(qū)別:從指定索引開始的字符串
boolean endsWith(String suffix) // 測試此字符串是否以指定的后綴結(jié)束
boolean matches(String regex) // 測試此字符串是否匹配給定的正則表達(dá)式
boolean contains(CharSequence s) // 當(dāng)且僅當(dāng)此字符串包含指定的 char 值序列時(shí)钻注,返回 true
3).比較
int compareTo(String anotherString) // 按字典順序比較兩個(gè)字符串。如:"abc".compareTo("acz") 結(jié)果為-1, b與c比,為-1
int compareToIgnoreCase(String str) // 按字典順序比較兩個(gè)字符串, 不考慮大小寫
boolean equals(Object anObject) // 將此字符串與指定的對(duì)象比較(內(nèi)容)
boolean equalsIgnoreCase(String anotherString) // 忽略大小寫比較
boolean contentEquals(StringBuffer sb) // 將此字符串與指定的StringBuffer比較
boolean contentEquals(CharSequence cs) // 將此字符串與指定的CharSequence比較
boolean regionMatches(int toffset, String other, int ooffset, int len) // 測試兩個(gè)字符串區(qū)域是否相等
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) // 測試兩個(gè)字符串區(qū)域是否相等
4).獲取
int length() 返回此字符串的長度
char charAt(int index) 返回指定索引處的char值
int codePointAt(int index) 返回指定索引處的字符(Unicode代碼點(diǎn))
int codePointBefore(int index) 返回指定索引之前的字符(Unicode代碼點(diǎn))
int codePointCount(int beginIndex, int endIndex) 返回此String的指定文本范圍中的Unicode代碼點(diǎn)數(shù)
int offsetByCodePoints(int index, int codePointOffset) 返回此String中從給定的index處偏移codePointOffset個(gè)代碼點(diǎn)的索引
void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) 將字符從此字符串復(fù)制到目標(biāo)字符數(shù)組
void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) 已過時(shí), 該方法無法將字符正確轉(zhuǎn)換為字節(jié). 從JDK 1.1起, 完成該轉(zhuǎn)換的首選方法是通過getBytes()方法, 該方法使用平臺(tái)的默認(rèn)字符集
byte[] getBytes(String charsetName) 使用指定的字符集將此 String 編碼為 byte 序列配猫,并將結(jié)果存儲(chǔ)到一個(gè)新的 byte 數(shù)組中
byte[] getBytes(Charset charset) 使用給定的 charset 將此 String 編碼到 byte 序列, 并將結(jié)果存儲(chǔ)到新的 byte 數(shù)組
byte[] getBytes() 使用平臺(tái)的默認(rèn)字符集將此 String 編碼為 byte 序列, 并將結(jié)果存儲(chǔ)到一個(gè)新的 byte 數(shù)組中
int hashCode() // 返回此字符串的哈希碼
int indexOf(int ch) // 返回指定字符在此字符串中第一次出現(xiàn)處的索引
int indexOf(int ch, int fromIndex) // 從指定的索引開始搜索
int indexOf(String str)
int indexOf(String str, int fromIndex)
int lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出現(xiàn)處的索引
int lastIndexOf(int ch, int fromIndex)
int lastIndexOf(String str)
int lastIndexOf(String str, int fromIndex)
String substring(int beginIndex) 返回一個(gè)新的字符串, 它是此字符串的一個(gè)子字符串
String substring(int beginIndex, int endIndex) 返回一個(gè)新字符串, 它是此字符串的一個(gè)子字符串
CharSequence subSequence(int beginIndex, int endIndex) 返回一個(gè)新的字符序列, 它是此序列的一個(gè)子序列
String concat(String str) 將指定字符串連接到此字符串的結(jié)尾
String replace(char oldChar, char newChar) 返回一個(gè)新的字符串, 它是通過用 newChar 替換此字符串中出現(xiàn)的所有 oldChar 得到的
String replaceFirst(String regex, String replacement) 使用給定的 replacement 替換此字符串匹配給定的正則表達(dá)式的第一個(gè)子字符串
String replaceAll(String regex, String replacement) 使用給定的 replacement 替換此字符串所有匹配給定的正則表達(dá)式的子字符串
String replace(CharSequence target, CharSequence replacement) 使用指定的字面值替換序列替換此字符串所有匹配字面值目標(biāo)序列的子字符串
String[] split(String regex, int limit) 根據(jù)匹配給定的正則表達(dá)式來拆分此字符串
String[] split(String regex) 根據(jù)給定正則表達(dá)式的匹配拆分此字符串
String toLowerCase(Locale locale) 使用給定 Locale 的規(guī)則將此 String 中的所有字符都轉(zhuǎn)換為小寫
String toLowerCase() // 使用默認(rèn)語言環(huán)境的規(guī)則將此 String 中的所有字符都轉(zhuǎn)換為小寫
String toUpperCase(Locale locale) // 使用給定Locale的規(guī)則將所有字符都轉(zhuǎn)換為大寫
String toUpperCase() // 使用默認(rèn)語言環(huán)境的規(guī)則將此 String 中的所有字符都轉(zhuǎn)換為大寫
String trim() 返回字符串的副本幅恋,忽略前導(dǎo)空白和尾部空白
String toString() 返回此對(duì)象本身(它已經(jīng)是一個(gè)字符串!)
char[] toCharArray() 將此字符串轉(zhuǎn)換為一個(gè)新的字符數(shù)組
native String intern() 返回字符串對(duì)象的規(guī)范化表示形式
5).靜態(tài)方法
static String format(String format, Object... args) 使用指定的格式字符串和參數(shù)返回一個(gè)格式化字符串
static String format(Locale l, String format, Object... args) 使用指定的語言環(huán)境、格式字符串和參數(shù)返回一個(gè)格式化字符串
static String valueOf(boolean/char/int/long/float/double b) // 返回指定類型參數(shù)的字符串表示形式
static String valueOf(Object obj) 返回 Object 參數(shù)的字符串表示形式
static String valueOf(char data[]) 返回 char 數(shù)組參數(shù)的字符串表示形式
static String valueOf(char data[], int offset, int count) // 返回 char 數(shù)組參數(shù)的特定子數(shù)組的字符串表示形式
static String copyValueOf(char data[], int offset, int count) // 返回指定數(shù)組中表示該字符序列的 String
static String copyValueOf(char data[]) 返回指定數(shù)組中表示該字符序列的 String
static String join(CharSequence delimiter, CharSequence... elements)
static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
2.2.1 字符串連接說明
連接多個(gè)字符串, 兩個(gè)連接的字符串之間用 +
(連接符) 相連, 連接之后生成一個(gè)新的字符串泵肄。
Java中的字符串不能分開兩行中寫, 如果一個(gè)字符串太長, 需要將這個(gè)字符串分在兩行上書寫, 此時(shí)可以使用"+"將兩個(gè)字符串連起來, 并在加號(hào)處換行
在字符串和其他數(shù)據(jù)類型連接時(shí), 同樣使用 +
連接符, 連接之后的返回值是字符串捆交。只要用 +
連接其中一個(gè)操作類型是字符串识埋,那么編譯器就會(huì)將另外的操作類型轉(zhuǎn)換成字符串形式, 所以應(yīng)謹(jǐn)慎地將其他數(shù)據(jù)類型與字符串相連
2.2.2 String類intern方法
(basic.str.StringDemo)
如果池中包含一個(gè)等于此String對(duì)象的字符串, 則返回池中的字符串, 否則將此String對(duì)象添加到池中, 并返回此String對(duì)象的引用
/**
* public String intern()返回字符串對(duì)象的規(guī)范化表示形式。
* 如果池中包含一個(gè)等于此String對(duì)象的字符串零渐,則返回池中的字符串
* 否則將此String對(duì)象添加到池中,并返回此String對(duì)象的引用
*/
public static void main(String[] args) {
String s0 = "kvill";
String s1 = new String("kvill");
String s2 = new String("kvill");
System.out.println(s0 == s1); //false
s1.intern();
s2 = s2.intern();
System.out.println(s0 == s1); //false
System.out.println(s0 == s1.intern()); //true
System.out.println(s0 == s2); //true
}
2.3 格式化字符串
(示例: basic.str.format.DataFormat, TimeFormat, DateAndTimeFormat, GeneralFormat, SystemOutPrintf)
格式化字符串: 主要包括日期格式化系忙、時(shí)間格式化诵盼、日期/時(shí)間組合的格式化和常規(guī)類型格式化
2.3.1 格式化方法
語法:
format(String format, Object... args)
format(Locale locale, String format, Object... args)
- locale:格式化過程要應(yīng)用的語言環(huán)境, 如果l位null, 則不進(jìn)行本地化
- format: 格式化轉(zhuǎn)換符
- args: 格式化字符串格式說明符引用的參數(shù), 如果還有格式說明符以外的參數(shù), 則忽略這些額外的參數(shù)
- 返回值: 一個(gè)格式化的字符串
2.3.2 日期格式化
常見的日期格式化轉(zhuǎn)換符
轉(zhuǎn)換符 | 說明 | 示例 |
---|---|---|
%te | 一個(gè)月中的某一天 | 6 |
%tb | 指定語言環(huán)境的月份簡稱 | Feb(英文), 二月(中文) |
%tB | 指定語言環(huán)境的月份全稱 | February(英), 二月(中) |
%ta | 指定語言環(huán)境的星期幾簡稱 | Mon(英), 星期一(中) |
%tA | 指定語言環(huán)境的星期幾全稱 | Monday(英), 星期一(中) |
%tc | 包括全部日期和時(shí)間信息 | 星期二 三月 25 13:37:22 CST 2008 |
%tY | 4位年份 | 2008 |
%ty | 2位年份 | 08 |
%tm | 月份 | 03 |
%td | 一個(gè)月中的第幾天(0~31) | 02 |
%tj | 一年中的第幾天(001~366) | 085 |
2.3.3 時(shí)間格式化
常見的時(shí)間格式化轉(zhuǎn)換符
轉(zhuǎn)換符 | 說明 | 示例 |
---|---|---|
%tH | 2位數(shù)字的24時(shí)制小時(shí)(00~23 | 14 |
%tI | 2位數(shù)字的12時(shí)制小時(shí)(01~12) | 05 |
%tk | 2位數(shù)字的24時(shí)制小時(shí)(0~23) | 5 |
%tl | 2位數(shù)字的12時(shí)制小時(shí)(1~12) | 10 |
%tM | 2位數(shù)字的分鐘(00~59) | 05 |
%tS | 2位數(shù)字的秒數(shù)(00~60) | 12 |
%tL | 3位數(shù)字的毫秒數(shù)(000~999) | 920 |
%tN | 9位數(shù)字的微秒數(shù)(000000000~999999999) | 062000000 |
%tp | 指定語言環(huán)境下上午或下午標(biāo)記 | 下午(中), pm(英) |
%tz | 相對(duì)于GMT RFC82格式的數(shù)字時(shí)區(qū)偏移量 | +0800 |
%tZ | 時(shí)區(qū)縮寫形式的字符串 | CST |
%ts | 1970-01-01 00:00:00至現(xiàn)在經(jīng)過的秒數(shù) | 1206426737 |
%tQ | 1970-01-01 00:00:00至現(xiàn)在經(jīng)過的毫秒數(shù) | 1206426737453 |
2.3.4 日期時(shí)間組合格式化
常見的時(shí)間格式化轉(zhuǎn)換符
轉(zhuǎn)換符 | 說明 | 示例 |
---|---|---|
%tF | "年-月-日"格式(4位年份) | 2008-03-25 |
%tD | "月/日/年"格式(2位年份) | 03/25/08 |
%tc | 全部日期和時(shí)間信息 | 星期二 三月 25 15:20:00 CST 2008 |
%tr | "時(shí):分:秒 PM(AM)"格式(12時(shí)制) | 03:22:06 下午 |
%tT | "時(shí):分:秒"格式(24時(shí)制) | 15:25:50 |
%tR | "時(shí):分"格式(24時(shí)制) | 15:25 |
2.3.5 常規(guī)類型格式化
常見的類型格式化轉(zhuǎn)換符
轉(zhuǎn)換符 | 說明 | 示例 |
---|---|---|
%b, %B | 結(jié)果被格式化為布爾值 | true |
%h, %H | 結(jié)果被格式化為散列碼 | A05A5198 |
%s, %S | 結(jié)果被格式化為字符串類型 | "abcd" |
%c, %C | 結(jié)果被格式化為字符類型 | 'a' |
%d | 結(jié)果被格式化為十進(jìn)制整數(shù) | 40 |
%o | 結(jié)果被格式化為八進(jìn)制整數(shù) | 11 |
%x, %X | 結(jié)果被格式化為十六進(jìn)制整數(shù) | 4b1 |
%e | 結(jié)果被格式化為用計(jì)算機(jī)科學(xué)計(jì)數(shù)法表示的十進(jìn)制數(shù) | 1.700000e+01 |
%a | 結(jié)果被格式化為帶有效位數(shù)和指數(shù)的十六進(jìn)制浮點(diǎn)值 | 0X1.C0000000000001P4 |
%n | 結(jié)果為特定平臺(tái)的行分隔符 | |
%% | 結(jié)果為字面值'%' | % |
%h, %H | 哈希值 | cd |
2.3.5 System.out.printf
printf格式控制的說明
轉(zhuǎn)換符 | 說明 |
---|---|
% | 表示格式說明的起始符號(hào), 不可缺少 |
- | 有-表示左對(duì)齊輸出, 如省略表示右對(duì)齊輸出 |
0 | 有0表示指定空位置0, 如省略表示指定空位不填 |
m.n | m指域?qū)? 即對(duì)應(yīng)的輸出項(xiàng)在輸出設(shè)備上所占的字符串 n指精度, 用于說明輸出的實(shí)型數(shù)的小數(shù)位數(shù), 缺省n=6 |
<strong> d格式: 用來輸出十進(jìn)制整數(shù) </strong> | |
%d | 按整型數(shù)據(jù)的實(shí)際長度輸出 |
%md | m為指定的輸出字段的寬度, 如果數(shù)據(jù)位數(shù)小于m, 左端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%5d\n", 123) |
%-md | -代表左對(duì)齊, 如果數(shù)據(jù)位數(shù)小于m, 右端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%-5d\n", 123) |
%05d | 0代表有空位置顯示0 如: printf("%05d\n", 123) |
<strong> o格式: 用來輸出八進(jìn)制整數(shù) </strong> | |
%o | 按整型數(shù)據(jù)的實(shí)際長度輸出 |
%mo | m為指定的輸出字段的寬度, 如果數(shù)據(jù)位數(shù)小于m, 左端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%5o\n", 123) |
%-mo | -代表左對(duì)齊, 如果數(shù)據(jù)位數(shù)小于m, 右端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%-5o\n", 123) |
%05o | 0代表有空位置顯示0 如: printf("%05o\n", 123) |
<strong> x格式: 用來輸出十六進(jìn)制整數(shù) </strong> | |
%x | 按整型數(shù)據(jù)的實(shí)際長度輸出 |
%mx | m為指定的輸出字段的寬度, 如果數(shù)據(jù)位數(shù)小于m, 左端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%5x\n", 123) |
%-mx | -代表左對(duì)齊, 如果數(shù)據(jù)位數(shù)小于m, 右端補(bǔ)空格, 若大于m, 按實(shí)際位數(shù)輸出, 如: printf("%-5x\n", 123) |
%05x | 0代表有空位置顯示0 如: printf("%05x\n", 123) |
<strong> c格式: 用來輸出字符 </strong> | |
%c | 輸出字符, 如: printf("%c\n", 97) |
<strong> f格式: 用來輸出浮點(diǎn)數(shù) </strong> | |
%f | 按浮點(diǎn)數(shù)據(jù)的輸出, 小數(shù)默認(rèn)精確到6位 |
%m.nf | m為指定的整數(shù)部分輸出位數(shù),m沒啥影響 n為指定的小數(shù)部分的輸出位數(shù), 四舍五入到精確的位數(shù) |
%-m.nf | -代表左對(duì)齊 |
<strong> e格式: 用來輸出浮點(diǎn)數(shù) </strong> | |
%e | 按浮點(diǎn)數(shù)據(jù)的輸出, 小數(shù)默認(rèn)精確到6位 |
%m.ne | m為指定的整數(shù)部分輸出位數(shù),m沒啥影響 n為指定的小數(shù)部分的輸出位數(shù), 四舍五入到精確的位數(shù) |
%-m.ne | -代表左對(duì)齊 |
<strong> s格式: 用來輸出浮點(diǎn)數(shù) </strong> | |
%s | |
%ms | |
%-ms | |
%m.nf | n代表要輸出的長度, 從左到右 |
%-m.nf | |
<strong> g格式: 用來輸出浮點(diǎn)數(shù) </strong> | |
%g | |
%mg | |
%-mg | |
%m.ng | n代表要輸出的長度, 從左到右 |
%-m.ng |
2.4 正則表達(dá)式
(basic.str.regex.RegexDemo, RegexCrawler)
2.4.1 判斷是否符合正則表達(dá)式的方法
為了檢查輸入的數(shù)據(jù)是否滿足某種格式, 從JDK1.4開始可以使用String類的matches()方法進(jìn)行判斷
語法:boolean matches(String regex)
- regex: 指定的正則表達(dá)式
- 返回值: 返回boolean類型
該方法用于告知當(dāng)前字符串是否匹配參數(shù)regex指定的正則表達(dá)式, 返回值是boolean類型, 如果當(dāng)前字符串與正則表達(dá)式匹配, 則該方法返回true, 否則返回false
2.4.2 正則表達(dá)式的元字符
正則表達(dá)式是由一些含有特殊意義的字符組成的字符串, 這些含有特殊意義的字符串稱為元字符
元字符 正則表達(dá)式中的寫法 含義
. "." 代表任意一個(gè)字符
\d "\\d" 代表0~9的任何一個(gè)數(shù)字
\D "\\D" 代表任何一個(gè)非數(shù)字字符
\s "\\s" 代表空白字符, 如'\t','\n'
\S "\\S" 代表非空白字符
\w "\\w" 代表可用作標(biāo)識(shí)符的字符, 但不包括"$"
\W "\\W" 代表不可用于標(biāo)識(shí)符的字符
\p{Lower} \\p{Lower} 代表小寫字母{a~z}
\p{Upper} \\p{Upper} 代表小寫字母{A~Z}
\p{ASCII} \\p{ASCII} ASCII字符
\p{Aplha} \\p{Aplha} 字母字符
\p{Digit} \\p{Digit} 十進(jìn)制數(shù)組,即[0~9]
\p{Alnum} \\p{Alnum} 數(shù)字或字母字符
\p{Punct} \\p{Punct} 標(biāo)點(diǎn)符號(hào): !#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph} \\p{Graph} 可見字符: [\p{Alnum}\p{Punct}]
\p{Print} \\p{Print} 可打印字符: [\p{Graph}\x20]
\p{Blank} \\p{Blank} 空格或制表符: [\t]
\p{Cntrl} \\p{Cntrl} 控制字符: [\x00~\x1F\x7F]
2.4.3 正則表達(dá)式的限定符
在使用正則表達(dá)式時(shí), 如果需要某一個(gè)類型元字符多次輸出, 逐個(gè)輸入就相當(dāng)麻煩, 這時(shí)可以使用正則表達(dá)式的限定元字符來重復(fù)次數(shù)
限定修飾符 意義 示例
? 0次或1次 A?
(.?) 非貪婪匹配 (.?)
* 0次或多次 A*
+ 1次或多次 A+
{n} 正好出現(xiàn)n次 A{2}
{n,} 至少出現(xiàn)n次 A{3,}
{n,m} 出現(xiàn)n~m次 A{2,6}
2.4.4 方括號(hào)中元字符的含義
字符 含義
[abc] 表示 a, b 或 c
[^abc] 表示 a, b, c 之外的任何字符
[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 之間不含 b 和 c 的所有字符
[a-z&&[^m-p]] a~z 之間不含 m~p 的所有字符
正則表達(dá)式對(duì)字符串的常見操作:
- 匹配: 其實(shí)使用的就是String類中的matches方法.
- 切割: 其實(shí)使用的就是String類中的split方法. 組:((A)(B(C)))
- 替換: 其實(shí)使用的就是String類中的replaceAll()方法.
- 獲取: 案例: 網(wǎng)頁爬蟲
將正則規(guī)則進(jìn)行對(duì)象的封裝
Pattern p = Pattern.compile("a*b");
// 通過正則對(duì)象的matcher方法字符串相關(guān)聯(lián)。獲取要對(duì)字符串操作的匹配器對(duì)象Matcher .
Matcher m = p.matcher("aaaaab");
// 通過Matcher匹配器對(duì)象的方法對(duì)字符串進(jìn)行操作银还。
boolean b = m.matches();
String priceStr = "匹配字符串:滿 2999 元減 100 元";
Pattern pricePattern = Pattern.compile("[^0-9]+([0-9]+?)[^0-9]+([0-9]+?)[^0-9]+"); // 結(jié)果:group(1) = 2999风宁,group(2) = 100
Matcher priceMatcher = pricePattern.matcher(priceStr);
if (priceMatcher.find()) {
System.out.println(priceMatcher.group(1));
System.out.println(priceMatcher.group(2));
}
2.5 StringBuffer 和 StringBuilder
(basic.str.StringBufferDemo, StringBuilderDemo)
StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類
在 AbstractStringBuilder 中也是使用字符數(shù)組保存字符串 char[] value,但是沒有用 final 關(guān)鍵字修飾蛹疯,所以這兩種對(duì)象都是可變的戒财。
StringBuilder 與 StringBuffer 的構(gòu)造方法都是調(diào)用父類構(gòu)造方法也就是 AbstractStringBuilder 實(shí)現(xiàn)的,大家可以自行查閱源碼捺弦。
AbstractStringBuilder.java
abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
StringBuffer 和 StringBuilder饮寞,常用于 。
特點(diǎn):
- 長度的可變
- 可以存儲(chǔ)不同類型的數(shù)據(jù)
- 最終要轉(zhuǎn)成字符串進(jìn)行使用
- 可以對(duì)字符串進(jìn)行修改
- 一般作為 字符串緩沖區(qū)列吼。存儲(chǔ)數(shù)據(jù)的容器幽崩,具備CRUD功能 C(create) U(update) R(read) D(delete)
1).添加
StringBuffer append(data);
StringBuffer append(StringBuffer sb)
StringBuffer insert(index, data);
2).刪除
StringBuffer delete(start, end); // 包含頭, 不包含尾
StringBuffer deleteCharAt(int index); // 刪除指定位置的元素
3).查找
char charAt(index);
int indexOf(string);
int lastIndexOf(string);
4).修改
StringBuffer replace(start, end, string);
void setCharAt(index, char);
5).其他
length(); // 獲取長度
setLength(int length); // 設(shè)置長度
reverse(); // 反轉(zhuǎn)顯示
toString(); // 字符串格式
StringBuilder 和 StringBuffer 的區(qū)別:
- StringBuffer是線程同步的. 通常用于多線程。(源碼中可以發(fā)現(xiàn)方法帶有synchronized關(guān)鍵字)
- StringBuilder是線程不同步的. 通常用于單線程. 它的出現(xiàn)提高效率.
- 在字符串緩存被單個(gè)線程使用時(shí)要比StringBuffer類快
線程安全性
String 中的對(duì)象是不可變的寞钥,也就可以理解為常量慌申,線程安全。
AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類理郑,定義了一些字符串的基本操作蹄溉,如 expandCapacity、append您炉、insert柒爵、indexOf 等公共方法。
StringBuffer 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖赚爵,所以是線程安全的餐弱。StringBuilder 并沒有對(duì)方法進(jìn)行加同步鎖,所以是非線程安全的囱晴。
性能
- 每次對(duì) String 類型進(jìn)行改變的時(shí)候膏蚓,都會(huì)生成一個(gè)新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象畸写。
- StringBuffer 每次都會(huì)對(duì) StringBuffer 對(duì)象本身進(jìn)行操作驮瞧,而不是生成新的對(duì)象并改變對(duì)象引用。
- 相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升枯芬,但卻要冒多線程不安全的風(fēng)險(xiǎn)论笔。
對(duì)于三者使用的總結(jié):
- 操作少量的數(shù)據(jù): 適用String
- 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用StringBuilder
- 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù): 適用StringBuffer