Java常用類(一) 一、String 類:(不可變的字元序列) 1.1 String:字元串,使用一對 " " 引起來表示。 String 類聲明為 final 的,不可被繼承。 String 類實現了 Serializable 介面:表示字元串是支持序列化的。實現了 Comparable 介面: ...
Java常用類(一)
目錄一、String 類:(不可變的字元序列)
1.1 String:字元串,使用一對 " " 引起來表示。
-
String 類聲明為 final 的,不可被繼承。
-
String 類實現了 Serializable 介面:表示字元串是支持序列化的。實現了 Comparable 介面:表示 String 可以比較大小的。
-
String 內部定義了 final char[] value 用於存儲字元串數據。( JDK8 與 JDK8 之前版本 )
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 ... }
-
String:代表不可變的字元序列。簡稱:不可變性。
體現:(1)當對字元串重新賦值時,需要重寫指定記憶體區域賦值,不能使用原有的 value 進行賦值。
(2)當對現有的字元串進行連接操作時,也需要重新指定記憶體區域賦值,不能使用原有的 value 進行賦值。
(3)String 的 replace() 方法修改指定字元或字元串時,也需要重新指定記憶體區域賦值,不能使用原有的 value 進行賦值。
-
通過字面量的方式(區別於new)給一個字元串賦值,此時的字元串值聲明在字元串常量池中。
-
字元串常量池中是不會存儲相同內容的字元串的。
public class test1{
public static void main(String[] args){
// 當對字元串重新賦值時,需要重寫指定記憶體區域賦值,不能使用原有的value進行賦值。
String s1 = "abc"; //字面量的定義方式
String s2 = "abc";
System.out.println(s1 == s2); //比較s1和s2的地址值:true
s1 = "hello";
System.out.println(s1 == s2); //比較s1和s2的地址值:false
System.out.println(s1); //hello
System.out.println(s2); //abc
// 當對現有的字元串進行連接操作時,也需要重新指定記憶體區域賦值,不能使用原有的value進行賦值。
String s3 = "abc";
s3 += "def";
System.out.println(s3); //abcdef
System.out.println(s2); //abc
// String的replace()方法修改指定字元或字元串時,也需要重新指定記憶體區域賦值,不能使用原有的value進行賦值。
String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4); //abc
System.out.println(s5); //mbc
}
}
1.2 String 對象的創建:
-
方式一:通過字面量定義的方式
方式二:通過 new + 構造器的方式
public class test2{
public static void main(String[] args){
//通過字面量定義的方式:此時的s1和s2的數據javaEE聲明在方法區中的字元串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通過new + 構造器的方式:此時的s3和s4保存的地址值,是數據在堆空間中開闢空間以後對應的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //false
System.out.println(s3 == s4); //false
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name)); //true
System.out.println(p1.name == p2.name); //true
p1.name = "Jerry";
System.out.println(p2.name);//Tom
}
}
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
-
面試題:String s = new String("abc");方式創建對象,在記憶體中創建了幾個對象?
兩個:一個是堆空間中 new 結構,另一個是 char[] 對應的常量池中的數據:"abc"。
1.3 String 不同拼接操作對比:
- 常量與常量的拼接結果在常量池。且常量池中不會存在相同內容的常量。
- 只要其中有一個是變數,結果就在堆中。
- 如果拼接的結果調用 intern() 方法,返回值就在常量池中。
public class test3{
public static void main(String[] args){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //false
System.out.println(s5 == s6); //false
System.out.println(s5 == s7); //false
System.out.println(s6 == s7); //false
String s8 = s6.intern(); //返回值得到的s8使用的常量值中已經存在的“javaEEhadoop”
System.out.println(s3 == s8); //true
final String s9 = "xiaozhao";
String s10 = s9 + "java";
String s11 = "xiaozhaojava";
System.out.println(s10 == s11); //true(原因:s9用final修飾,類似於常量,存儲在常量池中)
}
}
/*
s1 = s1 + "b";
說明:實際上原來的“a”字元串對象已經丟棄了,現在在堆空間中產生了一個字元串s1+"b"(也就是"ab")。如果多次執行這些改變串內容的 操作,會導致大量副本字元串對象存留在記憶體中,降低效率。如果這樣的操作放到迴圈中,會極大影響程式的性能。
*/
特殊例子:
public class StringTest {
String str = new String("good");
char[] ch = { 't', 'e', 's', 't' };
public void change(String str, char ch[]) { // 將實參str和ch的地址值傳遞給形參str和ch
// this.str = "test ok"; 如果使用該語句,則ex.str輸出為 test ok
str = "test ok";
System.out.println(str); // test ok
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str); // good
System.out.println(ex.ch); // best
}
}
1.4 String 類的常用方法
int length():返回字元串的長度:return value.length
char charAt(int index):返回某索引處的字元:return value[index]
boolean isEmpty():判斷是否是空字元串:return value.length == 0
String toLowerCase():使用預設語言環境,將 String 中的所有字元轉換為小寫
String toUpperCase():使用預設語言環境,將 String 中的所有字元轉換為大寫
String trim():返回字元串的副本,忽略前導空白和尾部空白
boolean equals(Object obj):比較字元串的內容是否相同
boolean equalsIgnoreCase(String anotherString):與equals方法類似,忽略大小寫
String concat(String str):將指定字元串連接到此字元串的結尾。 等價於用“+”
int compareTo(String anotherString):比較兩個字元串的大小
String substring(int beginIndex):返回一個新的字元串,它是此字元串的從beginIndex開始截取到最後的一個子字元串。
String substring(int beginIndex, int endIndex) :返回一個新字元串,它是此字元串從beginIndex開始截取到endIndex(不包含)的一個子字元串。
public class test1 {
public static void main(String[] args){}
String s1 = "HelloWorld";
System.out.println(s1.length()); // 10
System.out.println(s1.charAt(0)); // H
System.out.println(s1.isEmpty()); // false
String s2 = s1.toLowerCase();
System.out.println(s1); // HelloWorld(s1不可變的,仍然為原來的字元串)
System.out.println(s2); // helloworld(改成小寫以後的字元串)
String s3 = " he llo world ";
String s4 = s3.trim();
System.out.println(s3); // he llo world
System.out.println(s4); // he llo world
String s5 = "helloworld";
System.out.println(s1.equals(s5)); // false
System.out.println(s1.equalsIgnoreCase(s5)); // true
String s6 = s1.concat("ByJava");
System.out.println(s6); // HelloWorldByJava
String s7 = "abc";
String s8 = new String("abe");
System.out.println(s7.compareTo(s8));// -2
String s9 = "小釗學Java";
String s10 = s9.substring(2);
System.out.println(s9); // 小釗學Java
System.out.println(s10); // 學Java
String s11 = s9.substring(1, 4);
System.out.println(s11); // 釗學J
}
}
boolean endsWith(String suffix):測試此字元串是否以指定的尾碼結束
boolean startsWith(String prefix):測試此字元串是否以指定的首碼開始
boolean startsWith(String prefix, int toffset):測試此字元串從指定索引開始的子字元串是否以指定首碼開始
boolean contains(CharSequence s):當且僅當此字元串包含指定的 char 值序列時,返回 true
int indexOf(String str):返回指定子字元串在此字元串中第一次出現處的索引
int indexOf(String str, int fromIndex):返回指定子字元串在此字元串中第一次出現處的索引,從指定的索引開始
int lastIndexOf(String str):返回指定子字元串在此字元串中最右邊出現處的索引
int lastIndexOf(String str, int fromIndex):返回指定子字元串在此字元串中最後一次出現處的索引,從指定的索引開始反向搜索
// 註:indexOf和lastIndexOf方法如果未找到都是返回-1
public class test2{
public static void main(String[] args){
String s1 = "zhaohelloworldzhao";
boolean b1 = s1.endsWith("zhao");
System.out.println(b1); // true
boolean b2 = s1.startsWith("Zhao");
System.out.println(b2); // false
boolean b3 = s1.startsWith("hello",4);
boolean b4 = s1.startsWith("hello",5);
System.out.println(b3); // true
System.out.println(b4); // false
String s2 = "zhao";
System.out.println(s1.contains(s2)); // true
System.out.println(s1.indexOf("zhao")); // 0
System.out.println(s1.indexOf("zhao",1)); // 14
System.out.println(s1.lastIndexOf("zhao")); // 14
System.out.println(s1.lastIndexOf("zhao",6)); // 0
// 什麼情況下,indexOf(str)和lastIndexOf(str)返回值相同?
// 情況一:存在唯一的一個str。情況二:不存在str,均等於-1。
}
}
// 替換
String replace(char oldChar, char newChar):返回一個新的字元串,它是通過用 newChar 替換此字元串中出現的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替換序列替換此字元串所有匹配字面值目標序列的子字元串。
String replaceAll(String regex, String replacement) :使用給定的 replacement 替換此字元串所有匹配給定的正則表達式的子字元串。
String replaceFirst(String regex, String replacement) :使用給定的 replacement 替換此字元串匹配給定的正則表達式的第一個子字元串。
// 匹配
boolean matches(String regex):告知此字元串是否匹配給定的正則表達式。
// 切片
String[] split(String regex):根據給定正則表達式的匹配拆分此字元串。
String[] split(String regex, int limit):根據匹配給定的正則表達式來拆分此字元串,最多不超過 limit 個,如果超過了,剩下的全部都放到最後一個元素中。
public class test3{
public static void main(String[] args){
String s1 = "小釗學Java小釗";
String s2 = s1.replace('釗', '明');
System.out.println(s1); // 小釗學Java小釗
System.out.println(s2); // 小明學Java小明
String s = "12hello34world5java7891xiaozhao456";
//把字元串中的數字替換成!,如果結果中開頭和結尾有!的話去掉
String s3 = s.replaceAll("\\d+", "!");
String s4 = s.replaceAll("\\d+", "!").replaceAll("^,|,$", "");
System.out.println(s3); // !hello!world!java!xiaozhao!
System.out.println(s4); // hello!world!java!xiaozhao
String s5 = "12345";
//判斷s5字元串中是否全部有數字組成,即有1-n個數字組成
boolean matches = s5.matches("\\d+");
System.out.println(matches); // true
String tel = "020-4534289";
//判斷這是否是一個廣州的固定電話,且-後的號碼為7-8位
boolean result = tel.matches("020-\\d{7,8}");
System.out.println(result); // true
String s6 = "hello|world|java";
String[] strs = s6.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.print(strs[i] + " "); // hello world java
}
System.out.println();
String s7 = "hello.world.java";
String[] strs2 = s7.split("\\.");
for (int i = 0; i < strs2.length; i++) {
System.out.print(strs2[i] + " "); // hello world java
}
}
}
1.5 String 與基本數據類型、包裝類的轉換
-
字元串 >> 基本數據類型、包裝類
Integer 包裝類的 public static int parseInt(String s):可以將由“數字”字元組成的字元串轉換為整型。
類似地,使用 java.lang 包中的 Byte、Short、Long、Float、Double 類調相應的類方法可以將由“數字”字元組成的字元串,轉化為相應的基本數據類型。
-
基本數據類型、包裝類 >> 字元串
調用 String 類的 public String valueOf(int n) 可將 int 型轉換為字元串
相應的 valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b) 可由參數的相應類型到字元串的轉換
public class test1{
public static void main(String[] args){
String str1 = "123";
// int num = (int)str1;//錯誤的
int num = Integer.parseInt(str1);
String str2 = String.valueOf(num); // "123"
String str3 = num + "";
System.out.println(str1 == str3); // false(str3為堆地址值,str1為"123"在字元常量池的地址值)
}
}
1.6 String 與字元數組 char[] 的轉換
- String >> char[]:調用 String 的 toCharArray()
- char[] >> String:調用 String 的構造器
public class test2{
public static void main(String[] args){
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.print(charArray[i] + " "); // a b c 1 2 3
}
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2); // hello
}
}
1.7 String 與位元組數組 byte[] 的轉換
- 編碼:String >> byte[]:調用 String 的getBytes()
- 解碼:byte[] >> String:調用 String 的構造器
- 說明:解碼時,要求解碼使用的字元集必須與編碼時使用的字元集一致,否則會出現亂碼。
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123中國";
byte[] bytes = str1.getBytes(); // 使用預設的字元集,進行編碼。
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk"); // 使用gbk字元集進行編碼。
System.out.println(Arrays.toString(gbks));
String str2 = new String(bytes); // 使用預設的字元集,進行解碼。
System.out.println(str2);
String str3 = new String(gbks);
System.out.println(str3); // 出現亂碼。原因:編碼集和解碼集不一致!
String str4 = new String(gbks, "gbk");
System.out.println(str4); // 沒有出現亂碼。原因:編碼集和解碼集一致!
}
二、StringBuffer 類和 StringBuilder 類:(可變的字元序列)
2.1 StringBuffer 類:
-
java.lang.StringBuffer 代表可變的字元序列,JDK1.0 中聲明,可以對字元串內容進行增刪,此時不會產生新的對象。
-
很多方法與String相同。
-
作為參數傳遞時,方法內部可以改變值。
-
StringBuffer 類不同於 String,其對象必須使用構造器生成。有三個構造器:
StringBuffer():初始容量為16的字元串緩衝區。char[] value = new char[16];
StringBuffer(int size):構造指定容量的字元串緩衝區。
StringBuffer(String str):將內容初始化為指定字元串內容。
-
StringBuffer 類的常用方法:
StringBuffer append(xxx):提供了很多的append()方法,用於進行字元串拼接
StringBuffer delete(int start,int end):刪除指定位置的內容
StringBuffer replace(int start, int end, String str):把[start,end)位置替換為str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse():把當前字元序列逆轉
public int indexOf(String str):返回指定子字元串在此字元串中第一次出現處的索引
public String substring(int start,int end):返回一個從start開始到end索引結束的左閉右開區間的子字元串
public int length():返回字元串的(有效)長度
public char charAt(int n ):返回某索引處的字元
public void setCharAt(int n ,char ch):修改n索引處的字元為ch
public class test1{
public static void main(String[] args){
StringBuffer s1 = new StringBuffer("abc");
s1.setCharAt(0,'m');
System.out.println(s1); // mbc
StringBuffer s2 = new StringBuffer();
System.out.println(s2.length()); // 0
s1.append(1);
s1.append('1');
System.out.println(s1); // mbc11
// s1.delete(2,4); // mb1
// s1.replace(2,4,"hello"); // mbhello1
// s1.insert(2,false); // mbfalsec11
// s1.reverse(); // 11cbm
String s2 = s1.substring(1, 3);
System.out.println(s1); // mbc11
System.out.println(s1.length()); // 5
System.out.println(s2); // bc
}
}
2.2 StringBuilder 類
-
StringBuilder 和 StringBuffer 非常類似,均代表可變的字元序列,而且提供相關功能的方法也一樣。
-
面試題:對比 String、StringBuffer、StringBuilder
String:不可變的字元序列;底層使用 char[] 存儲
StringBuffer:可變的字元序列;線程安全的,效率低;底層使用 char[] 存儲
StringBuilder:可變的字元序列;jdk5.0新增的,線程不安全的,效率高;底層使用 char[] 存儲
註意:作為參數傳遞的話,方法內部String不會改變其值,StringBuffer和StringBuilder 會改變其值。
-
StringBuffer 類和 StringBuilder 類初始容量均為 16 的字元串緩衝區,如果要添加的數據底層數組盛不下了,那就需要擴容底層的數組。預設情況下,擴容為原來容量的 2 倍加 2,同時將原有數組中的元素複製到新的數組中。
因此開發中建議大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity) 。
-
對比 String、StringBuffer、StringBuilder 三者的效率:
從高到低排列:StringBuilder > StringBuffer > String