448 常用類的概述
449 String類的概述
String:字元串,使用一對'' ''引起來表示
1,String聲明為final的,不可被繼承
2.String實作了Serializable接口:表示字元串是支援序列化的
實作了Comparable接口:表示String可以比較大小
3,String内部定義了final char[ ] value用于存儲字元串資料
4.String代表不可變的字元序列,簡稱:不可變性
展現:1.當對字元串重新指派時,需要重新指定記憶體區域指派,不能使用原有的value進行指派
2.當對現有的字元串進行連接配接操作時,也需要重新指定記憶體區域指派,不能使用原有的value進行指派
3.當調用String的replace()方法修改字元或字元串時, 也需要重新指定記憶體區域指派,不能使用原有的value進行指派
450 了解String的不可變性
public void test1(){
String s1="abc";//字面量的定義方式
String s2="abc";
//s1="hello";
System.out.println(s1==s2);//比較s1和s2的位址值
System.out.println(s1);//hello
System.out.println(s2);//abc
String s3="abc";
s3+="def";
System.out.println(s3);//abcdef
System.out.println(s2);//abc
String s4="abc";
String s5=s4.replace('a','m');
System.out.println(s4);
System.out.println(s5);
}
}
5.通過字面量的方式(差別于new)給一個字元串指派,此時的字元串值聲明在字元串常量池中
6.字元串常量池中不會存儲相同内容的字元串的
451 String不同執行個體化方式的對比
String str = "hello";
//本質上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
String的執行個體化方式:
方式一:通過字面量定義的方式
方式二:通過new+構造器的方式
面試題:String s=new String(“abc”);方式建立對象,在記憶體中建立了幾個對象?
兩個:一個是堆空間中new結構,另一個是char[]對應的常量池中的資料:“abc”
public class StringTest{
public void test2(){
//通過字面量定義的方法,此時的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;
}
public Person(){
}
}
452 String不同拼接操作的對比
public class StringTest{
public void test3(){
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=s5.intern();//傳回值得到的s8使用的常量值中已經存在的“javaEEHadoop”
System.out.println(s3==s8);//true
}
結論
1.常量與常量的拼接結果是在常量池。且常量池中不會存在相同内容的變量
2. 隻要其中有一個是變量,結果就在堆中
3.如果拼接的結果調用intern()方法,傳回值就在常量池中
453 String的一道面試題
/**
* 一道面試題
*/
public class StringTest {
String str = new String("good");
char[] ch = { 't', 'e', 's', 't' };
public void change(String str, char ch[]) {
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
}
}
454 JVM中涉及字元串的記憶體結構
455 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 equals IgnoreCase(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 void test2(){
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2));//false
System.out.println(s1.equalsIgnoreCase(s2));//true
String s3 = "abc";
String s4 = s3.concat("def");
System.out.println(s4);//abcdef
String s5 = "abc";
String s6 = new String("abe");
System.out.println(s5.compareTo(s6));//-2 //涉及到字元串的排序
String s7 = "周圍好吵啊";
String s8 = s7.substring(2);
System.out.println(s7);
System.out.println(s8);
String s9 = s7.substring(0, 2);
System.out.println(s9);
}
public class StringMethodTest{
public void test1(){
String s1="HelloWorld";
System.out.println(s1.length());
System.out.println(s1.charAt(0));
System.out.println(s1.charAt(9));
System.out.println(s1.isEmpty());
String s2=s1.tolowerCase();
System.out.println(s1);//s1是不可變的,仍然為原來的字元串
System.out.println(s2);//改成小寫以後的字元串
String s3=" he llo world ";
String s4=s3.trim();
System.out.println(s3);
System.out.println(s4);
}
}
456 String的常用方法2
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 void test3(){
String str1="helloworld";
boolean b1=str1.endsWith("rld");
System.out.println(b1);
boolean b2=str1.endsWith("He");
System.out.println(b2);
boolean b3=str1.endsWith("ll", 2);
System.out.println(b3);
String str2="wo";
System.out.println(str1.contains(str2));
System.out.println(str1.indexOf("lol");//-1
System.out.println(str1.indexOf("lo",5);//-1
String str3 = "hellorworld";
System.out.println(str3.lastIndexOf("or"));
System.out.println(str3.lastIndexOf("or",6));
}
//什麼情況下,indexOf(str)和lastIndexOf(str)傳回值相同?
//情況一:存在唯一的一個str。情況二:不存在str
457 String的常用方法3
替換:
* 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 void test4(){
String str1="北京尚矽谷教育北京";
String str2=str1.replace('北','東');
System.out.println(str1);
System.out.println(str2);
String str3=str1.replace('北京','上海');
System.out.println(str3);
System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//把字元串中的數字替換成,,如果結果中開頭和結尾有,的話去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);
System.out.println("*************************");
str = "12345";
//判斷str字元串中是否全部有數字組成,即有1-n個數字組成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判斷這是否是一個杭州的固定電話
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);
}
458 String與基本資料類型包裝類的轉換
import org.junit.Test;
/**
* 涉及到String類與其他結構之間的轉換
*/
public class StringTest1 {
/**
* 複習
* String與基本資料類型、包裝類之間的轉換
*
* String --> 基本資料類型、包裝類:調用包裝類的靜态方法:parseXxx(str)
* 基本資料類型、包裝類 --> String:調用String重載的valueOf(xxx)
*/
@Test
public void test1(){
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
}
}
459 String與char[]的轉換
public void test2(){
String str1="abc123";
char[] charArray=str1.toCharArrar();
for(int i=0;i<charArray.length;i++){
System.out.println(charArray[i]);
}
char[] arr=new char[]{'h','e','l','l','o');
String str2=new String(arr);
System.out.println(str2);
}
460 String與byte[ ]之間的轉換
public void test3(){
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);//沒有出現亂碼。原因:編碼集和解碼集一緻!
}
編碼:字元串---位元組(看得懂---看不懂的二進制資料)
解碼:編碼的逆過程,位元組---字元串(看不懂的二進制資料---看得懂)
編碼:String --> byte[]:調用String的getBytes()
解碼:byte[] --> String:調用String的構造器
說明:解碼時,要求解碼使用的字元集必須與編碼時使用的字元集一緻,否則會出現亂碼
461 解決一個拼接問題
462 面試中String算法考察的說明
463 StringBuffer和StringBuilder的介紹
/**
* String、StringBuffer、StringBuilder三者的異同?
*
* String:不可變的字元序列;底層使用char[]存儲
* StringBuffer:可變的字元序列;線程安全的,效率低;底層使用char[]存儲
* StringBuilder:可變的字元序列;jdk5.0新增的,線程不安全的,效率高;底層使用char[]存儲
*
*/
464 StringBuffer的源碼分析
import org.junit.Test;
/**
* 關于StringBuffer和StringBuilder的使用
*/
public class StringBufferBuilderTest {
/**
*
* 源碼分析:
* String str = new String();//char[] value = new char[0];
* String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
*
* StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底層建立了一個長度是16的數組。
* System.out.println(sb1.length());//
* sb1.append('a');//value[0] = 'a';
* sb1.append('b');//value[1] = 'b';
*
* StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
*
* //問題1.System.out.println(sb2.length());//3
* //問題2.擴容問題:如果要添加的資料底層數組盛不下了,那就需要擴容底層的數組。
* 預設情況下,擴容為原來容量的2倍 + 2,同時将原有數組中的元素複制到新的數組中。
*
* 意義:開發中建議大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)
*
*/
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(0,'m');
System.out.println(sb1);
StringBuffer sb2 = new StringBuffer();
System.out.println(sb2.length()); //0
}
}
465 StringBuffer中的常用方法
import org.junit.Test;
/**
* 關于StringBuffer和StringBuilder的使用
*/
public class StringBufferBuilderTest {
/**
* 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)
*
* 總結:
* 增:append(xxx)
* 删:delete(int start,int end)
* 改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
* 查:charAt(int n )
* 插:insert(int offset, xxx)
* 長度:length();
* 周遊:for() + charAt() / toString()
*
*/
@Test
public void test2(){
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);
s1.append('1');
System.out.println(s1);
// s1.delete(2,4);
// s1.replace(2,4,"hello");
// s1.insert(2,false);
// s1.reverse();
String s2 = s1.substring(1,3);
System.out.println(s1);
System.out.println(s1.length());
System.out.println(s2);
}
}
466 String、StringBuffer、StringBuilder效率對比
import org.junit.Test;
/**
* 關于StringBuffer和StringBuilder的使用
*/
public class StringBufferBuilderTest {
/**
* 對比String、StringBuffer、StringBuilder三者的效率:
* 從高到低排列:StringBuilder > StringBuffer > String
*
*/
@Test
public void test3(){
//初始設定
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//開始對比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的執行時間:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的執行時間:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的執行時間:" + (endTime - startTime));
}
}
467 System類中擷取時間戳的方法
System
類提供的
public static long currentTimeMillis()
用來傳回目前時間與1970年1月1日0時0分0秒之間以毫秒為機關的時間差。
import org.junit.Test;
/**
* JDK 8之前日期和時間的API測試
*/
public class DateTimeTest {
//1.System類中的currentTimeMillis()
@Test
public void test1(){
long time = System.currentTimeMillis();
//傳回目前時間與1970年1月1日0時0分0秒之間以毫秒為機關的時間差。
//稱為時間戳
System.out.println(time);
}
}
468 Java中兩個Date類的使用
import org.junit.Test;
import java.util.Date;
/**
* JDK 8之前日期和時間的API測試
*/
public class DateTimeTest {
/**
* java.util.Date類 ---> 表示特定的瞬間,精确到毫秒
* |---java.sql.Date類
*
* 1.兩個構造器的使用
* >構造器一:Date():建立一個對應目前時間的Date對象
* >構造器二:建立指定毫秒數的Date對象
* 2.兩個方法的使用
* >toString():顯示目前的年、月、日、時、分、秒
* >getTime():擷取目前Date對象對應的毫秒數。(時間戳)
*
* 3. java.sql.Date對應着資料庫中的日期類型的變量
* >如何執行個體化
* >如何将java.util.Date對象轉換為java.sql.Date對象
*
*/
@Test
public void test2(){
//構造器一:Date():建立一個對應目前時間的Date對象
Date date1 = new Date();
System.out.println(date1.toString()); //Sat May 09 20:09:11 CST 2020
System.out.println(date1.getTime()); //1589026216998
//構造器二:建立指定毫秒數的Date對象
Date date2 = new Date(1589026216998L);
System.out.println(date2.toString());
//建立java.sql.Date對象
java.sql.Date date3 = new java.sql.Date(35235325345L);
System.out.println(date3); //1971-02-13
//如何将java.util.Date對象轉換為java.sql.Date對象
//情況一:
// Date date4 = new java.sql.Date(2343243242323L);
// java.sql.Date date5 = (java.sql.Date) date4;
//情況二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
}
}
473 String課後算法題目1
将一個字元串進行反轉。将字元串中指定部分進行反轉。比如“abcdefg”反轉為”abfedcg”
方法一:
public class StringDemo{
public String reverse(String str,int startIndex,int endIndex){
if(str!=null){
char[] arr=str.toCharArray();
for(int x=startIndex,y=endIndex;x<y;x++,y--){
char temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
return new String(arr);
}
return null;
}
@Test
public void testReverse(){
String str="abcdefg";
String reverse=reverse(str,2,5);
System.out.prinltn(reverse);
}
}
478 SimpleDateFormat的使用
jdk 8之前的日期時間的API測試
1.System類中currentTimeMillis();
2.java.util.Date和子類java.sql.Data
/**
* SimpleDateFormat的使用:SimpleDateFormat對日期Date類的格式化和解析
* 1.兩個操作
* 1.1格式化:日期---》字元串
* 1.2解析:格式化的逆過程,字元串---》日期
*
* 2.SimpleDateFormat的執行個體化
*/
public class DateTimeTest{
public void testSimpleDateFormat(){
//執行個體化SimpleDateFormat
SimpleDateFormat sdf=new SimpleDateFormat();
//格式化:日期---字元串
Date date=new Date();
System.out.println(date);
String format=sdf.format(date);
System.out.println(format);
//解析:格式化的逆過程,字元串---日期
String str = "19-12-18 上午11:43";
Date date1 = sdf.parse(str);
System.out.println(date1); //Wed Dec 18 11:43:00 CST 2019
//*************按照指定的方式格式化和解析:調用帶參的構造器*****************
// SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1); //02020.五月.10 公元 04:32 下午
//解析:要求字元串必須是符合SimpleDateFormat識别的格式(通過構造器參數展現),
//否則,抛異常
Date date2 = sdf1.parse("02020.五月.10 公元 04:32 下午");
System.out.println(date2); //Sun May 10 16:32:00 CST 2020
}
}