Java常用類詳解
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
作者 | 13roky
來源 | urlify.cn/QZfqaa
1. String類
1.1 String的特性
String類:代表字符串。Java程序中的所有字符串字面值(如“abc”)都作為此類的實(shí)例實(shí)現(xiàn)。
String是一個(gè)final類,代表不可變的字符序列。
String字符串是常量,用雙引號(hào)引起來表示。他們的值在創(chuàng)建之后不能更改。
String對(duì)象的找字符內(nèi)容是存儲(chǔ)在一個(gè)字符數(shù)組value[]中的。(jdk新版本已改為使用byte類型的數(shù)組value[]存放)

1.2 String字面量賦值的內(nèi)存理解
字面量賦值是直接在常量池中賦值的
Demo:
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
/**
* String 的使用
*
* @author 13roky
* @date 2021-04-24 10:34
*/
public class StringTest {
/*
String:字符串,使用一對(duì)""來表示.
1.String類是被聲明為final的,不可被繼承.
2.String實(shí)現(xiàn)了Serializable接口:標(biāo)識(shí)字符串是支持序列化的. (io流)
實(shí)現(xiàn)了Comparable接口:可以比較大小.
3.String內(nèi)部定義了final char[] value用于存儲(chǔ)字符串?dāng)?shù)字. final表示數(shù)組和其元素不能被修改。(為了節(jié)省jvm的內(nèi)存空間jdk9已經(jīng)改為byte[]類型數(shù)組)
4.String:代表不可變的字符序列。簡稱:不可變性。
體現(xiàn):1.當(dāng)對(duì)字符串重新賦值時(shí),需要重新指定內(nèi)存區(qū)域賦值,不能使用原有的value進(jìn)行賦值.(因?yàn)樵械膙alue是final的)
2.當(dāng)對(duì)現(xiàn)有的字符串進(jìn)行連接操作時(shí),需要重新指定內(nèi)存區(qū)域賦值,不能使用原有的value賦值.
3.當(dāng)調(diào)用String的replace()方法修改字符或字符串時(shí),也必須重新指定內(nèi)存區(qū)域賦值,不能使用原有的value賦值.
5.通過字面量的方式(區(qū)別于new)給一個(gè)字符串賦值,此時(shí)的字符串值生命在字符串常量池中.
6.字符串常量池中是不會(huì)存儲(chǔ)相同內(nèi)容的字符串的.
*/
@Test
public void test01(){
//字面量的定義方式, 在內(nèi)存中用的是同一個(gè)內(nèi)存地址
String s1 = "abc";
String s2 = "abc";
//==比較的是地址值,為true說明s1和s2在內(nèi)存中指向的是同一個(gè)位置
System.out.println(s1 == s2);//true
s1 = "hello";
System.out.println(s1);//hello
System.out.println(s2);//abc
System.out.println("================================================");
String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
System.out.println(s2);//abc
System.out.println("================================================");
String s4 = "adb";
String s5 = s4.replace('a','m');
System.out.println(s4);//abc
System.out.println(s5);//mbc
}
}
圖解:
由于
字符串常量池中是不會(huì)存儲(chǔ)相同內(nèi)容的字符串的,所以在字符串常量池中s1和s2指向同一個(gè)內(nèi)存地址。

由于String內(nèi)部定義了final char[] value用于存儲(chǔ)字符串?dāng)?shù)字,final表示數(shù)組和其元素不能被修改,其也就有了
不可變的字符序列的性質(zhì)。所以改變s1取值為hello后,并不會(huì)改變字符串常量池中的對(duì)應(yīng)位置的值,而是會(huì)新開辟一個(gè)內(nèi)存地址存放hello值,并且s1指向新的內(nèi)存地址。

以下圖解類似。

1.3 String new方式賦值的內(nèi)存理解
Demo:
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
/**
* String 的使用
*
* @author 13roky
* @date 2021-04-24 10:34
*/
public class StringTest {
/*
String實(shí)例化方式測試:
方式一: 通過字面量定義的方式
方式二: 通過new + 構(gòu)造器的方式
面試題:String s = new String("abc);方式創(chuàng)建對(duì)象,在內(nèi)存中創(chuàng)建了幾個(gè)對(duì)象?
兩個(gè):一個(gè)是堆空間中new結(jié)構(gòu),另一個(gè)是char[]對(duì)應(yīng)的常量池中的數(shù)據(jù)"abc"
*/
@Test
public void test2() {
//通過字面量定義的方式:此時(shí)的s1和s2的數(shù)據(jù)javaEE生命在方法區(qū)中的字符串常量池中.
String s1 = "javaEE";
String s2 = "javaEE";
//通過new + 構(gòu)造器的方式:此時(shí)的s3和s4保存的地址值是數(shù)據(jù)在堆空間中開辟空間后對(duì)應(yīng)的地址值.
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
System.out.println(s3.equals(s4));//true
System.out.println("=================================================");
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
}
}
class Person{
public String name;
public int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
}
}
圖解:
new的結(jié)構(gòu)是存在于堆中的,比如 String s3 = new String("javaEE");

1.4 String 拼接字面量和變量的方式賦值
Demo:
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
/**
* String 的使用
*
* @author 13roky
* @date 2021-04-24 10:34
*/
public class StringTest {
/*
1.常量與常量的拼接結(jié)果在常量池。且常量池中不會(huì)存在享同內(nèi)容的常量。
2.只要其中有一個(gè)是變量,結(jié)果就在堆中。
3.如果拼接的結(jié)果調(diào)用intern()方法,返回值就會(huì)在常量池中。
*/
@Test
public void test03() {
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";//引號(hào)中的為字面量,這里是字面量的拼接
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
final String s8 = "hadoop";
String s9 = "javaEE" + s8;
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
System.out.println(s3 == s9);//true
String s10 = s5.intern();//返回值得到的s8使用的常量值中已經(jīng)存在的”javaEEhadoop“(s5.intern返回的時(shí)常量池中對(duì)應(yīng)的內(nèi)存地址)
System.out.println(s3 == s10);//true
}
}
圖解:
常量與常量的拼接,結(jié)果直接保存在常量池中。如
String s4 = "javaEE" + "hadoop";,如果常量池中存在“javaEEhadoop”,那么s4直接指向其地址。只要拼接賦值時(shí),其中有一個(gè)是變量,那么結(jié)果就會(huì)存在于堆中,如
String s5 = s1 + "hadoop";,棧中的變量名s5指向堆中對(duì)應(yīng)的地址0x0001,堆中的地址又指向常量池的地址0x1214。s5指向的是堆中的內(nèi)存地址0x0001,但是方法
s5.intern返回的直接是常量池中的地址。所以String s10 = s5.intern();這行代碼會(huì)讓s10直接指向常量池對(duì)應(yīng)的內(nèi)存地址。

package com.broky.commonClass.exer;
import java.util.Arrays;
/**
* @author 13roky
* @date 2021-04-26 7:27
*/
public class StringValueChangeEx {
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) {
StringValueChangeEx test01 = new StringValueChangeEx();
test01.change(test01.str, test01.ch);
//這里涉及字符串的拼接,所以會(huì)用toString方法,而char中的toString返回的是哈希值,所以要用arrays類
System.out.println(test01.str + " and " + Arrays.toString(test01.ch)); //good and [C@2f4d3709
System.out.println(test01.str); //good
System.out.println(test01.ch); //test
}
}
1.5 String類常用方法
int Length():返回字符的長度: return value.Lengthchar charAt(int index):返回某索引處的字return vaLue[index]booLean isEmpty():判斷是否是空字符牢: return value. Length == 0String toLowercase():使用默認(rèn)語言環(huán)境,將 String中的所有字符轉(zhuǎn)換為小寫String toUppercase():使用默認(rèn)語言環(huán)境,將 String中的所有字符轉(zhuǎn)換為大寫String trim():返回字符的副本,忽略前導(dǎo)空白和尾部空白boolean equals(Object obj):比較字符的內(nèi)容是否相同booLean equalsIgnoreCase(String anotherString):與equls方法類似,忽略大小寫String concat(string str):將指定字符牢連接到此字符的結(jié)尾。等價(jià)于用"+"int compare To(String anotherstring):比較兩個(gè)字符的大小String substring(int beginIndex):返回一個(gè)新的字符,它是此字符的從 beginIndex開始截取到最后一個(gè)子字符串.String substring(int beginIndex, int endindex):返回一個(gè)新字符串,它是此字符從beginIndex開始截取到endIndex(不包含)的一個(gè)子字符串.
Demo:
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
import java.util.Locale;
/**
* @author 13roky
* @date 2021-04-26 21:47
*/
public class CommonMethod {
/*
int Length():返回字符的長度: return value.Length
char charAt( nt index):返回某索引處的字return vaLue[index]
booLean isEmpty():判斷是否是空字符牢: return value. Length == 0
String toLowercase():使用默認(rèn)語言環(huán)境,將 String中的所有字符轉(zhuǎn)換為小寫
String toUppercase():使用默認(rèn)語言環(huán)境,將 String中的所有字符轉(zhuǎn)換為大寫
String trim():返園字符的副本,忽略前導(dǎo)空白和尾部空白
boolean equals(Object obj):比較字符的內(nèi)容是否相同
booLean equalsIgnoreCase(String anotherString):與equls方法類似,忽略大小寫
String concat(string str):將指定字符牢連接到此字符的結(jié)尾。等價(jià)于用"+"
int compare To(String anotherstring):比較兩個(gè)字符的大小
String substring(int beginIndex):返回一個(gè)新的字符,它是此字符的從 beginIndex開始截取到最后一個(gè)子字符串.
String substring(int beginIndex, int endindex):返回一個(gè)新字符串,它是此字符從beginIndex開始截取到endIndex(不包含)的一個(gè)子字符串.
*/
@Test
public void test01(){
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);
System.out.println(s2);
String s3 = " he llo world ";
String s4 = s3.trim();
System.out.println(s3);
System.out.println(s4);
}
@Test
public void test02(){
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2));
System.out.println(s1.equalsIgnoreCase(s2));
String s3 = "abc";
String s4 = "def".concat(s3);
System.out.println(s4);
String s5 = "abc";
String s6 = new String("abd");
System.out.println(s5.compareTo(s6));
String s7 = "13roky學(xué)Java";
String s8 = s7.substring(2,6);
System.out.println(s7);
System.out.println(s8);
}
}
boolean endsWith(String suffix):測試此字符串是否以指定的后綴結(jié)束boolean startsWith(String prefix):測試此字符串是否以指定的前綴開始boolean startsWith(String prefix, int toffset):測試此字符串從指定索引開始的子字符串是否以指定的前綴開始boolean contains(CharSequence s):當(dāng)且僅當(dāng)此字符串包含指定的char值序列時(shí),返回trueint indexOf(String str): 返回指定子字符串在此字符串中第一次出現(xiàn)處的索引int indexOf(String str,int fromIndex):返回指定子字符串在此字符串中第一次出現(xiàn)處的索引,從指定的索引處開始int lastIndexOf(String str):返回指定子字符串在此字符串中最右邊出現(xiàn)處的索引int lastIndexOf(String str,int fromIndex):返回指定子字符串在此字符串中最后一次出現(xiàn)處的索引,從指定的索引開始反向搜索(從右往左搜索)indexOf和lastindexOf方法如果未找到,返回結(jié)果都是-1
Demo:
package com.broky.commonClass;
import jdk.jfr.DataAmount;
import org.junit.jupiter.api.Test;
import java.util.Locale;
/**
* @author 13roky
* @date 2021-04-26 21:47
*/
public class CommonMethod {
/*
boolean endsWith(String suffix):測試此字符串是否以指定的后綴結(jié)束
boolean startsWith(String prefix):測試此字符串是否以指定的前綴開始
boolean startsWith(String prefix, int toffset):測試此字符串從指定索引開始的子字符串是否以指定的前綴開始
boolean contains(CharSequence s):當(dāng)且僅當(dāng)此字符串包含指定的char值序列時(shí),返回true
int indexOf(String str): 返回指定子字符串在此字符串中第一次出現(xiàn)處的索引
int indexOf(String str,int fromIndex):返回指定子字符串在此字符串中第一次出現(xiàn)處的索引,從指定的索引處開始
int lastIndexOf(String str):返回指定子字符串在此字符串中最右邊出現(xiàn)處的索引
int lastIndexOf(String str,int fromIndex):返回指定子字符串在此字符串中最后一次出現(xiàn)處的索引,從指定的索引開始反向搜索(從右往左搜索)
indexOf和lastindexOf方法如果未找到,返回結(jié)果都是-1
*/
@Test
public void test03(){
String str1 = "helloworld";
boolean b1 = str1.endsWith("rld");
System.out.println(b1);
boolean b2 = str1.startsWith("He");
System.out.println(b2);
boolean b3 =str1.startsWith("ll",2);
System.out.println(b3);
String str2 = "wo";
System.out.println(str1.contains(str2));
System.out.println(str1.indexOf("lol"));
System.out.println(str1.indexOf("l"));
System.out.println(str1.indexOf("lo", 5));
String str3 = "hellorworld";
System.out.println(str3.lastIndexOf("or"));
System.out.println(str3.lastIndexOf("or",6));
}
//什么情況下,indexOf(str)和lastIndexOf(str)返回值相同?
//情況一:存在唯一的一個(gè)str.
//情況二:不存在str
}
替換:
String replace(char oldChar,char newChar):返回一個(gè)新的字符串,它是通過用newChar替換oldChar
String replace(CharSequence target,CharSequence replacement):使用字面值替換序列替換此字符串所有匹配字面值目標(biāo)序列的子字符串.
String replaceAll(String regex,String replacement):使用給定的replacement替換此字符串多有匹配給定的正則表達(dá)式的子字符串
String replaceFirst(String regex,String replacement):使用給定的replacement替換此字符串匹配給定的正則表達(dá)式的第一個(gè)子字符串.匹配:
boolean matches(String regex):告知此字符串是否匹配給定得正則表達(dá)式切片:
String[] split(String regex):根據(jù)給定的正則表達(dá)式的匹配拆分此字符串
String[] split(String regex,int limit):根據(jù)匹配給定的正則表達(dá)式來分此字符串,最多不超過limit個(gè),如果超出,剩下的全部都放到最后一個(gè)元素
Demo:
package com.broky.commonClass;
import jdk.jfr.DataAmount;
import org.junit.jupiter.api.Test;
import java.util.Locale;
/**
* @author 13roky
* @date 2021-04-26 21:47
*/
public class CommonMethod {
/*
替換
String replace(char oldChar,char newChar):返回一個(gè)新的字符串,它是通過用newChar替換oldChar
String replace(CharSequence target,CharSequence replacement):使用字面值替換序列替換此字符串所有匹配字面值目標(biāo)序列的子字符串.
String replaceAll(String regex,String replacement):使用給定的replacement替換此字符串多有匹配給定的正則表達(dá)式的子字符串
String replaceFirst(String regex,String replacement):使用給定的replacement替換此字符串匹配給定的正則表達(dá)式的第一個(gè)子字符串.
匹配:
boolean matches(String regex):告知此字符串是否匹配給定得正則表達(dá)式
切片:
String[] split(String regex):根據(jù)給定的正則表達(dá)式的匹配拆分此字符串
String[] split(String regex,int limit):根據(jù)匹配給定的正則表達(dá)式來分此字符串,最多不超過limit個(gè),如果超出,剩下的全部都放到最后一個(gè)元素
*/
@Test
public void test04(){
String str1 = "13roky學(xué)Java";
String str2 = str1.replace('學(xué)','寫');
System.out.println(str1);
System.out.println(str2);
String str3 = str1.replace("13roky", "geek");
System.out.println(str3);
System.out.println("=====================================================");
String str = "123klnjklsdnafdmc123pojasvapos";
String string = str.replace("\\d+",",").replaceAll("^,|,$","|");
System.out.println(string);
str = "12345";
//判斷str字符串中是否全部有數(shù)字組成,即有1-n個(gè)數(shù)字組成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判斷一個(gè)電話是否是杭州的
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);
System.out.println("================================================");
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
str2 = "hello.world.java";
String[] strs2 = str2.split("\\|");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}
}
}
1.6 String與其它類型的轉(zhuǎn)換
demo:
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* String類與其他結(jié)構(gòu)之間的轉(zhuǎn)換
* String 與 char[] 之間的轉(zhuǎn)換
* String 與 byte[] 之間的轉(zhuǎn)換
*
* @author 13roky
* @date 2021-05-02 19:33
*/
public class StringChange {
/*
復(fù)習(xí):String與其他數(shù)據(jù)類型,包裝類之間的轉(zhuǎn)換
String --> 基本數(shù)據(jù)類型、包裝類:調(diào)用包裝類的靜態(tài)方法:parseXxx(str)
基本數(shù)據(jù)類型、包裝類 ——》String:調(diào)用String重載的valueOf(xxx) 或者直接拼接“”
*/
@Test
public void test(){
String str = "123";
//int num = (int) str; 只有子父類的關(guān)系才可以使用強(qiáng)制類型轉(zhuǎn)換
int num = Integer.parseInt(str);
String str2 = String.valueOf(num);
String str3 = num + "";
}
/*
String 與 char[] 之間的轉(zhuǎn)換
String --> char[] :String類中的toCharArray()方法
char[] --> String :String的構(gòu)造器
*/
@Test
public void test02(){
String str = "abcde";
char[] c1 = str.toCharArray();
for (int i = 0; i < c1.length; i++) {
System.out.println(c1[i]);
}
char[] c2 = new char[]{'f','s','c','a'};
String str2 = new String(c2);
System.out.println(str2);
}
/*
String 與 byte[] 之間的轉(zhuǎn)換
編碼:String --> byte[] :調(diào)用String的getBytes()
解碼:
轉(zhuǎn)化的時(shí)候會(huì)涉及編碼和解碼
編碼:字符串 --> 字節(jié) (看得懂轉(zhuǎn)換為看不懂的二進(jìn)制數(shù)據(jù))
解碼 字節(jié) --> 字符串 (看不懂的二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為看得懂)
*/
@Test
public void test03() throws UnsupportedEncodingException {
String str = "abc123此方";
// 使用ide默認(rèn)的編碼集進(jìn)行轉(zhuǎn)換
byte[] b1 = str.getBytes();
// 字節(jié)byte類型 采用ASCLL編碼 由于ASCLL中沒有中文編碼,所以中文會(huì)轉(zhuǎn)為默認(rèn)的編碼如(UTF-8,UTF-8中一個(gè)漢字占三位)然后再轉(zhuǎn)為ASCLL
System.out.println(Arrays.toString(b1));
// 使用 gbk 字符集進(jìn)行編碼,需要處理異常
byte[] b2 = str.getBytes("gbk");
System.out.println(Arrays.toString(b2));
System.out.println("=======================================");
// 使用ide默認(rèn)的編碼集進(jìn)行解碼
String str2 = new String(b1);
System.out.println(str2);
// 出現(xiàn)亂碼。原因:編碼及和解碼集不一致倒置的
String str3 = new String(b2);
System.out.println(str3);
// 指定編碼集
String str4 = new String(b2, "gbk");
System.out.println(str4);
}
}
1.7 常見算法題目
模擬一個(gè)trim方法,去除字符串兩端的空格。
將一個(gè)字符串進(jìn)行反轉(zhuǎn)。將字符串中間指定部分進(jìn)行反轉(zhuǎn)。比如“abcdefg”反轉(zhuǎn)為“abfedcg”。
獲取一個(gè)字符串在另一個(gè)字符串中出現(xiàn)的次數(shù)。
獲取兩個(gè)字符串中最大的相同字符串。
將字符串中字符進(jìn)行自然順序排序。Arrays.sort()
package com.broky.commonClass.exer;import org.junit.jupiter.api.Test;import java.nio.CharBuffer;import java.util.Arrays;import java.util.Objects;/** * 四道常見String算法題目 * 1. 模擬一個(gè) trim 方法,去除字符串兩端的空格。 * * @author 13roky * @date 2021-05-08 10:06 */public class Algorithms { @Test public void testMyTrim() { String s1 = " 123 "; s1.trim(); s1 = myTrim(s1); System.out.println(s1); } // 模擬一個(gè) trim 方法,去除字符串兩端的空格。 public String myTrim(String str) { if (str != null) { int start = 0;// 用于記錄從前往后首次索引位置不是空格的位置的索引 int end = str.length() - 1;// 用于記錄從后往前首次索引位置不是空格的位置的索引 while (start < end && str.charAt(start) == ' ') { start++; } while (start < end && str.charAt(end) == ' ') { end--; } if (str.charAt(start) == ' ') { return ""; } return str.substring(start, end + 1); } return null; } @Test public void testMyReverse() { System.out.println(myReverse01("abcdefg", 2, 5)); System.out.println(myReverse02("abcdefg", 2, 5)); System.out.println(myReverse03("abcdefg", 2, 5)); } /* 將一個(gè)字符串進(jìn)行反轉(zhuǎn)。將字符串中指定部分進(jìn)行反轉(zhuǎn)。比如“abcdefg”反轉(zhuǎn)為“abfedcg” */ // 方式一:轉(zhuǎn)換為char[] public String myReverse01(String str, int start, int end) { if (str != null) { char[] chars = str.toCharArray(); char tmp = 0; for (int s = start, e = end; s < e; s++, e--) { tmp = chars[s]; chars[s] = chars[e]; chars[e] = tmp; } return new String(chars); } return null; } // 方式二:使用String的拼接 public String myReverse02(String str, int start, int end) { if (str != null) { String partOne = str.substring(0, start); String parThree = str.substring(end + 1); for (int i = end; i >= start; i--) { partOne += str.charAt(i); } partOne += parThree; return partOne; } return null; } // 方式三:使用StringBuffer 或 StringBuilder 替換String public String myReverse03(String str, int start, int end) { StringBuilder builder = new StringBuilder(str.length()); builder.append(str.substring(0, start)); for (int i = end; i >= start; i--) { builder.append(str.charAt(i)); } builder.append(str.substring(end + 1)); return String.valueOf(builder); } /* 獲取一個(gè)字符串在另一個(gè)字符串中出現(xiàn)的次數(shù)。 如:獲取 "ab" 在 “abkkcakabkebfkabkskab” 出現(xiàn)的次數(shù) */ @Test public void testGetCount() { getCount01("ab", "abkkcakabkebfkabkskab"); getCount02("ab", "abkkcakabkebfkabkskab"); } // 方法一: public int getCount01(String mainStr, String subStr) { int n = 0; for (int i = 0; i < subStr.length() - mainStr.length() + 1; i++) { if (mainStr.charAt(0) == subStr.charAt(i)) { if (mainStr.equals(subStr.substring(i, i + mainStr.length()))) { n++; } } } System.out.println(n); return n; } // 方法二: public int getCount02(String mainStr, String subStr) { int count = 0; int index = 0; if (subStr.length() >= mainStr.length()) {// while ((index = subStr.indexOf(mainStr)) != -1) {// count++;// subStr = subStr.substring(index + mainStr.length());// } // 改進(jìn) while ((index = subStr.indexOf(mainStr,index)) != -1) { count++; index += mainStr.length(); } System.out.println(count); return count; } else { return 0; } }}
2. StringBuffer 和 StringBuilder類
2.1 String、StringBuffer、StringBuilder 三者的異同
String:不可變的字符序列,底層使用char[]進(jìn)行存儲(chǔ)
StringBuffer:可變的字符序列,線程安全的,效率低,底層使用char[]進(jìn)行存儲(chǔ)
StringBuilder:可變的字符序列,線程不安全的,效率高,jdk5.0新特性,底層使用char[]進(jìn)行存儲(chǔ)
源碼分析:
String:
String str = new String(); // 底層代碼為 char[] value = new char[0];
String str1 = new String("abc"); // 底層代碼為 char[] value = new char[]{'a','b','c'};StringBuffer:
String sb1 = new StringBuffer(); // char[] value = new char[16];底層創(chuàng)建了一個(gè)長度是16的數(shù)組
sb1.append('a'); // value[0] = 'a';
sb1.append('b'); // value[1] = 'b';問題:
System.out.println(sb1.length()); 返回的是有的值count,而不是底層開辟的空間value.length.
擴(kuò)容問題,如果要添加的數(shù)據(jù)底層數(shù)組盛不下了,那就需要擴(kuò)容底層的數(shù)組。默認(rèn)情況下,擴(kuò)容為原來容量的2倍+2(源碼中采用了位運(yùn)算<<),同時(shí)將原有數(shù)組中的元素復(fù)制到新數(shù)組中。
總結(jié):
開發(fā)中盡量不要用String,String不可變,效率最差,每次都會(huì)新造。而StringBuufer和StringBuilder只有長度不夠用的時(shí)候才去擴(kuò)容并復(fù)制。
開發(fā)中如果知道會(huì)頻繁使用append時(shí),建議使用StringBuffer的指定容量的構(gòu)造器,避免之后進(jìn)行擴(kuò)容。
2.2 StringBuffer 類的常用方法
StringBuffer append(xx):提供了很多的 append()方法,用于進(jìn)行字符拼接
StringBuffer delete( int start, int end):刪除指定位置的內(nèi)容,本身發(fā)生改變,并返回值。
StringBuffer replace( int start, int end, String str):把 start,end)位置替換為str
StringBuffer insert( int offset,xxx):在指定位置插入xxx
StringBuffer reverse():把當(dāng)前字符序列逆轉(zhuǎn)
public int indexof(string str)
pubLic String substring (int start, int end) 返回一個(gè)從Start開始到End結(jié)束的左閉右開區(qū)間的子字符串,本身值并未變化
public int Length
public char charAt(int n)
public void setcharAt (int n, char ch)
總結(jié):
增:append(xx)
刪: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()方法鏈的原理:s1.append().append().append(); s1調(diào)用完append后返回的依舊是s1,可以繼續(xù)調(diào)用append
package com.broky.commonClass.exer;import org.junit.jupiter.api.Test;/** * StringBuffer 的常用方法 * * @author 13roky * @date 2021-05-07 13:27 */public class StringBufferMethod { @Test public void test(){ StringBuffer s1 = new StringBuffer("abc"); s1.append(1); s1.append("234"); System.out.println(s1.delete(2, 4)); System.out.println(s1); System.out.println(s1.replace(2, 4, "hello")); System.out.println(s1.reverse()); }}
關(guān)于append方法
package com.broky.commonClass;import org.junit.jupiter.api.Test;public class StringBufferBuilderTest { @Test public void test2(){ String str = null; StringBuffer sb = new StringBuffer(); //StringBuffer 的 append 方法會(huì)將null值轉(zhuǎn)換為字符“null”加入 sb.append(str); System.out.println(sb.length());//4 System.out.println(sb);//"null" StringBuffer sb2 = new StringBuffer(str); System.out.println(sb2); }}
2.3 String、StringBuffer、StringBuilder 三者的效率
效率:StringBuilder > StringBuffer > String
package com.broky.commonClass;import org.junit.jupiter.api.Test; /** * String StringBuffer StringBuilder 效率測試 */ @Test public void timeTest() { 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 執(zhí)行時(shí)間" + (endTime - startTime)); startTime = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { builder.append(String.valueOf(i)); } endTime = System.currentTimeMillis(); System.out.println("StringBuilder 執(zhí)行時(shí)間" + (endTime - startTime)); startTime = System.currentTimeMillis(); for (int i = 0; i < 20000; i++) { text = text + String.valueOf(i); } endTime = System.currentTimeMillis(); System.out.println("String 執(zhí)行時(shí)間" + (endTime - startTime)); }}
3. JDK8 之前的日期和時(shí)間 api 相關(guān)類
3.1 java.lang.System 類
System 類提供的 public static long currentTimeMillis() 用來返回當(dāng)前時(shí)間與1970年1月1日0時(shí)0分0秒之間以毫秒為單位的時(shí)間差。
3.2 java.util.Date 和 java.sql.Date 類
兩個(gè)構(gòu)造器的使用
構(gòu)造器一:Date():創(chuàng)建一個(gè)對(duì)應(yīng)當(dāng)前時(shí)間的Date對(duì)象
構(gòu)造器二:創(chuàng)建指定毫秒數(shù)的Date對(duì)象兩個(gè)方法的使用
toString():顯示當(dāng)前的年、月、日、時(shí)、分、秒
getTime():獲取當(dāng)前Date對(duì)象對(duì)應(yīng)的毫秒數(shù)。(時(shí)間戳)java.sql.Date 對(duì)應(yīng)這數(shù)據(jù)庫中的日期類型的變量
實(shí)例化
將 sql.date 轉(zhuǎn)換 util.date: 多態(tài)直接賦值
將 util.date 轉(zhuǎn)換 sql.date: 通過共同的getTime()時(shí)間戳實(shí)現(xiàn)
Demo:
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.util.Date;/** * JDK8 之前的日期和時(shí)間的 api 測試 * * @author 13roky * @date 2021-05-08 9:15 */public class DateTimeTest { /* System類提供的 public static long currentTimeMillis() 用來返回當(dāng)前時(shí)間與1970年1月1日0時(shí)0分0秒之間以毫秒為單位的時(shí)間差。 */ @Test public void test() { long time = System.currentTimeMillis(); System.out.println(time); } /* java.util.Date 類 |---java.sql.Date 類 數(shù)據(jù)庫 1. 兩個(gè)構(gòu)造器的使用 > 構(gòu)造器一:Date():創(chuàng)建一個(gè)對(duì)應(yīng)當(dāng)前時(shí)間的Date對(duì)象 > 構(gòu)造器二:創(chuàng)建指定毫秒數(shù)的Date對(duì)象 2. 兩個(gè)方法的使用 > toString():顯示當(dāng)前的年、月、日、時(shí)、分、秒 > getTime():獲取當(dāng)前Date對(duì)象對(duì)應(yīng)的毫秒數(shù)。(時(shí)間戳) 3. java.sql.Date 對(duì)應(yīng)這數(shù)據(jù)庫中的日期類型的變量 > 實(shí)例化 > 將 sql.date 轉(zhuǎn)換 util.date: 多態(tài)直接賦值 > 將 util.date 轉(zhuǎn)換 sql.date: 通過共同的getTime()時(shí)間戳實(shí)現(xiàn) */ @Test public void test02() { // 構(gòu)造器一:Date():創(chuàng)建一個(gè)對(duì)應(yīng)當(dāng)前時(shí)間的Date對(duì)象 Date date1 = new Date(); System.out.println(date1.toString()); System.out.println(date1.getTime()); // 構(gòu)造器二:創(chuàng)建指定毫秒數(shù)的Date對(duì)象 Date date2 = new Date(1620437519431L); java.sql.Date date3 = new java.sql.Date(1620437519431L); System.out.println(date3); // 將 util.date 轉(zhuǎn)換 sql.date: // 情況一 Date date4 = new java.sql.Date(1620437519431L); java.sql.Date date5 = (java.sql.Date) date4; // 情況二 Date date6 = new Date(); java.sql.Date date7 = new java.sql.Date(date6.getTime()); /* 當(dāng)new的是父類的時(shí)候,如果強(qiáng)轉(zhuǎn)為子類,那么編譯時(shí)不會(huì)報(bào)錯(cuò),運(yùn)行時(shí)會(huì)報(bào)錯(cuò),因?yàn)閚ew的父類缺少子類特有的屬性和方法 當(dāng)new的是子類的時(shí)候,但是賦給了父類,這時(shí)候是可以強(qiáng)轉(zhuǎn)成子類的,如情況一 */ }}
注意:
使用Data的構(gòu)造器,設(shè)置時(shí)間會(huì)存在 偏移量 的問題
Demo:
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.util.Date;/** * JDK8 之前的日期和時(shí)間的 api 測試 * * @author 13roky * @date 2021-05-08 9:15 */public class DateTimeTest { // Date中的偏移量 @Test public void test01() { /* 由于構(gòu)造方法存在一個(gè)偏移量,年份是從1990年開始,月份是從0開始所以構(gòu)造時(shí)應(yīng)該減去偏移量 */ Date date1 = new Date(2020, 9, 8); System.out.println(date1); // Fri Oct 08 00:00:00 CST 3920 date1 = new Date(2020 - 1900, 9 - 1, 8); System.out.println(date1); // Tue Sep 08 00:00:00 CST 2020 }}
3.3 SimpleDateFormat 類
SimpleDateFormat 是用來 格式化 Date 類中 時(shí)間格式的 和 對(duì)格式進(jìn)行解析成 Date 的類
可以使用默認(rèn)格式,也可以自定義格式。
兩個(gè)操作
1.1 格式化:日期 ---> 字符串
1.2 解析:格式化的逆過程,字符串 ---> 日期SimpleDateFormat 的實(shí)例化
Demo
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;/** * jdk 8 之前的日期時(shí)間的API測試 * 1. System類中currentTimeMillis(); * 2. java.util.Date 和 子類 java.sql.Date * 3. SimpleDateFormat * 4. Calendar * * @author 13roky * @date 2021-05-09 12:53 */public class DateTimeTest2 { /* SimpleDateFormat 的使用:SimpleDateFormat對(duì)日期 Date 類的格式化和解析 1. 兩個(gè)操作 1.1 格式化:日期 ---> 字符串 1.2 解析:格式化的逆過程,字符串 ---> 日期 2. SimpleDateFormat 的實(shí)例化 */ @Test public void testSimpleDateFormat() throws ParseException { // 實(shí)例化SimpleDateFormat:使用默認(rèn)的構(gòu)造器 SimpleDateFormat sdf = new SimpleDateFormat(); // 格式化:日期 ---> 字符串 Date date = new Date(); System.out.println(date); String format = sdf.format(date); System.out.println(format); // 解析: 格式化的逆過程,字符串 ---> 日期 String str = "2021/5/9 下午1:04"; Date date1 = null; date1 = sdf.parse(str); System.out.println(date1); //********************************* // SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa"); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String format1 = sdf1.format(date); System.out.println(format1); Date date2 = sdf1.parse("2021-05-09 01:09:56"); System.out.println(date2); }}
練習(xí):
字符串“2020-02-23”轉(zhuǎn)化為java.sql.Date
三天打魚兩天曬網(wǎng) 1990-01-01 視頻分析:P482480.尚硅谷_常用類-SimpleDateFormat的課后練習(xí)2
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date; @Test public void testEx01() throws ParseException { //練習(xí)一:字符串“2020-02-23”轉(zhuǎn)化為java.sql.Date String str ="2020-02-23"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse(str); System.out.println(date); java.sql.Date sqlDate = new java.sql.Date(date.getTime()); System.out.println(sqlDate); } @Test public void testEx02() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date startDate = sdf.parse("1990-01-01"); long oneDay = sdf.parse("1990-01-02").getTime() - startDate.getTime(); long period = oneDay * 5; // long now = sdf.parse(sdf.format(new Date())).getTime() - startDate.getTime(); long now = sdf.parse("1990-01-06").getTime() - startDate.getTime() + oneDay; if (now % period > 3 * oneDay || now % period == 0) { System.out.println("曬網(wǎng)"); } else { System.out.println("打魚"); } }}
3.4 Calendar 類
calendar類是一個(gè)抽象類,是可變的
demo
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;/** * jdk 8 之前的日期時(shí)間的API測試 * 1. System類中currentTimeMillis(); * 2. java.util.Date 和 子類 java.sql.Date * 3. SimpleDateFormat * 4. Calendar * * @author 13roky * @date 2021-05-09 12:53 */public class DateTimeTest2 { /* Calendar 日歷類(抽象類)的使用 */ @Test public void testCalendar(){ // 1. 實(shí)例化 // 方式一: 創(chuàng)建其子類 (GregorianCalendar)的對(duì)象 // 方式二:調(diào)用其靜態(tài)方法getInstance() // 兩種創(chuàng)建方法本質(zhì)上一樣 Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getClass()); // 2.常用方法 //get() int days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); //set() calendar.set(Calendar.DAY_OF_MONTH,22); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); //add() calendar.add(Calendar.DAY_OF_MONTH,-3); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); //getTime(): 日歷類-->Date Date date = calendar.getTime(); System.out.println(date); //setTime(): Date--->日歷類 Date date1 = new Date(); calendar.setTime(date1); days = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(days); }}
注意
獲取月份時(shí):一月是0,二月是1,以此類推12月是11
獲取星期時(shí):周日是1,周二是2.。。。周六是7
3.5 JDK8 之前時(shí)間日期api的一些問題
如果我們可以跟別人說:“我們在1502643933071見晚了!”那么就再簡單不過了。但是我們希望時(shí)間與量夜和四季有關(guān),于是事情就變復(fù)雜了。JDK10中包含了個(gè) java util. Date類,但是它的大多數(shù)方法已經(jīng)在JDK11引入 Calendar類之后被棄用而 Calendar并不比Date好多少。它們面臨的問題是:
**可變性: **像日期和時(shí)間這樣的類應(yīng)該是不可變的。
**偏移性: **Date中的年份是從1900開始的,而月份都從0開始。
格式化: 格式化只對(duì)Date有用, Calendar則不行
此外,它們也不是線程安全的;不能處理閏秒等。
因此我們需要引入 以下 新的時(shí)間日期api來處理這些問題。
4. JDK8 中新的時(shí)間日期 api
第三次引入的API是成功的,并且Java8中引入的 java. time API 已經(jīng)糾正了過去的缺陷,將來很長一段時(shí)間內(nèi)它都會(huì)為我們服務(wù)。
Java8 吸收了Joda-Time的精華,以一個(gè)新的開始為Java創(chuàng)建優(yōu)秀的AP新的 java. time中包含了所有關(guān)于本地日期( LocalDate)、本地時(shí)間( LocalTime)、本地日期時(shí)間( LocalDate Time)、時(shí)區(qū)( Zoned Date Time)和持續(xù)時(shí)間( Duration)的類。歷史悠久的Date類新增了 tolnstant()方法,用于把Date轉(zhuǎn)換成新的表示形式。這些新增的本地化時(shí)間口期 API 大大簡化了日期時(shí)間和本地化的管理。
在JDK8 之前joda-time是作為jar包的形式導(dǎo)入項(xiàng)目使用的,在jdk8 的時(shí)候官方將其引入.
4.1 LocalDate、LocalTime、LocalDateTime 類的使用
實(shí)例化:
實(shí)例化方式一:使用靜態(tài)方法
now() / now(zoneld zone)獲取當(dāng)前的日期時(shí)間實(shí)例化方式二:使用靜態(tài)方法
of()自定義時(shí)間,無 Date 中偏移量的問題
方法 :
now() / now(zoneld zone)of()getXxx()獲取相關(guān)屬性withXxxx()設(shè)置相關(guān)屬性plusXxx()在現(xiàn)有基礎(chǔ)上加上指定數(shù)據(jù)minusXxx()在現(xiàn)有基礎(chǔ)上減去指定數(shù)據(jù)
說明 :
三個(gè)類都具有不可變性
LocalDateTime 相較于 LocalDate , LocalTime 使用頻率更高
類似于 jdk8 之前的 Calendar 類
Demo:
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;/** * jdk 8 中的時(shí)間日期 api * * @author 13roky * @date 2021-05-10 7:05 */public class JDK8DateTimeTest { /* LocalDate、LocalTime、LocalDateTime 類的使用: */ @Test public void test01(){ // 實(shí)例化方式一:使用靜態(tài)方法 now() / now(zoneld zone) 獲取當(dāng)前的日期時(shí)間 LocalDateTime localDateTime = LocalDateTime.now(); LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); System.out.println(localDateTime); System.out.println(localDate); System.out.println(localTime); // 實(shí)例化方式二:of() 可以自定義時(shí)間,無 Date 中偏移量的問題 LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 1, 4, 23, 43); System.out.println(localDateTime1); // getXxx() 獲取相關(guān)屬性 System.out.println(localDateTime.getDayOfMonth()); System.out.println(localDateTime.getDayOfWeek()); System.out.println(localDateTime.getMonth()); System.out.println(localDateTime.getMonthValue()); System.out.println(localDateTime.getMinute()); // withXxxx() 設(shè)置相關(guān)屬性, 具有不可變性 LocalDate localDate1 = localDate.withDayOfMonth(20); System.out.println(localDate1); LocalDateTime localDateTime2 = localDateTime.withHour(16); System.out.println(localDateTime); System.out.println(localDateTime2); //plusXxx() 在現(xiàn)有基礎(chǔ)上加上指定數(shù)據(jù) LocalDateTime localDateTime3 = localDateTime.plusMonths(3); System.out.println(localDateTime); System.out.println(localDateTime3); // minusXxx() 在現(xiàn)有基礎(chǔ)上減去指定數(shù)據(jù) LocalDateTime localDateTime4 = localDateTime.minusMonths(3); System.out.println(localDateTime); System.out.println(localDateTime4); }}
4.2 Instant 類的使用
Instant : 時(shí)間線上的瞬時(shí)點(diǎn). 這可能被用來記錄應(yīng)用程序中的事件時(shí)間戳.
方法 :
now()靜態(tài)方法, 返回 UTC 時(shí)區(qū)的 Instant 類對(duì)象atOffset()添加 默認(rèn)時(shí)區(qū) 與 當(dāng)前需要時(shí)區(qū) 的 時(shí)間 的 偏移量toEpochMilli()獲取 1970年1月1日0時(shí)0分0秒 (UTC) 開始的毫秒數(shù)ofEpochMilli()靜態(tài)方法, 通過給定的毫秒數(shù)獲取 Instant 的實(shí)例
Demo :
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.time.*;/** * jdk 8 中的時(shí)間日期 api * * @author 13roky * @date 2021-05-10 7:05 */public class JDK8DateTimeTest { /* Instant 的使用 */ @Test public void test02() { // now : 獲取本初子午線的時(shí)間 Instant instant = Instant.now(); //格林威治時(shí)間 System.out.println(instant); // 添加 默認(rèn)時(shí)區(qū) 與 當(dāng)前需要時(shí)區(qū) 的 時(shí)間 的 偏移量 OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); // 獲取 1970年1月1日0時(shí)0分0秒 (UTC) 開始的毫秒數(shù) long milli = instant.toEpochMilli(); System.out.println(milli); // ofEpochMilli 通過給定的毫秒數(shù)獲取 Instant 的實(shí)例 Instant instant1 = Instant.ofEpochMilli(1620783200875L); System.out.println(instant1); }}
4.3 DateTimeFormatter 類
用于格式化和解析 LocalDate、LocalTime、LocalDateTime
類似于 SimpleDateFormat
格式化方式 :
預(yù)定義的標(biāo)準(zhǔn)格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME;
本地化相關(guān)的格式。如:ofLocalizedDateTime(FormatStyle.LONG);
自定義的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss E");
解析方式 :
parse()方法
Demo :
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.time.*;import java.time.format.DateTimeFormatter;import java.time.format.FormatStyle;import java.time.temporal.TemporalAccessor;/** * jdk 8 中的時(shí)間日期 api * * @author 13roky * @date 2021-05-10 7:05 */public class JDK8DateTimeTest { /* DateTimeFormatter:格式化或解析日期、時(shí)間 類似于SimpleDateFormat */ @Test public void test03() { // 方式一:預(yù)定義的標(biāo)準(zhǔn)格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME; DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime); String s = formatter.format(localDateTime); System.out.println(s); // 因?yàn)槭褂脴?biāo)準(zhǔn)格式進(jìn)行格式化,所以 localDateTime 格式化前后的值基本沒有變化,但是類型變變?yōu)榱?nbsp;String // 解析:字符串-->日期 TemporalAccessor parse = formatter.parse("2021-05-12T20:48:52.1539765"); System.out.println(parse); // 方式二: // 本地化相關(guān)的格式。如:ofLocalizedDateTime(FormatStyle.LONG); // FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 適用于LocalDateTime DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); String s1 = formatter1.format(localDateTime); System.out.println(s1); // 本地化相關(guān)的格式。如:ofLocalizedDate() // FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 適用于LocalDateTime DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); String s2 = formatter2.format(LocalDate.now()); System.out.println(s2); /* 可能會(huì)報(bào)錯(cuò) : java.time.DateTimeException: Unable to extract ZoneId from temporal 參考:https://stackoverflow.com/questions/59531046/java-time-datetimeexception-unable-to-extract-zoneid-from-temporal */ // 方式三:自定義的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss E"); DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); String s3 = formatter3.format(localDateTime); System.out.println(s3); // 解析 TemporalAccessor parse1 = formatter3.parse("2021-05-12 09:24:47"); System.out.println(parse1); }}
4.4 其它API
ZoneId:該類中包含了所有的時(shí)區(qū)信息,一個(gè)時(shí)區(qū)的ID,如 Europe/Paris
ZonedDateTime:一個(gè)在ISO-8601日歷系統(tǒng)時(shí)區(qū)的日期時(shí)間,如 2007-12- 03T10:15:30+01:00 Europe/Paris。
其中每個(gè)時(shí)區(qū)都對(duì)應(yīng)著ID,地區(qū)ID都為“{區(qū)域}/{城市}”的格式,例如:Asia/Shanghai等
Clock:使用時(shí)區(qū)提供對(duì)當(dāng)前即時(shí)、日期和時(shí)間的訪問的時(shí)鐘。
持續(xù)時(shí)間:Duration,用于計(jì)算兩個(gè)“時(shí)間”間隔
日期間隔:Period,用于計(jì)算兩個(gè)“日期”間隔
TemporalAdjuster : 時(shí)間校正器。有時(shí)我們可能需要獲取例如:將日期調(diào)整 到“下一個(gè)工作日”等操作。
TemporalAdjusters : 該類通過靜態(tài)方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的實(shí)現(xiàn)。
5. Comparable 和 Comparator 接口
5.1 Comparable 接口 自然排序
用于對(duì)象與對(duì)象的比較, Comparable屬于自然排序
說明:
Java中的對(duì)象, 正常情況下, 只能進(jìn)行比較:==或!= 不能使用>或<
但是在開發(fā)場景中, 我們需要對(duì)多個(gè)對(duì)象進(jìn)行排序, 言外之意, 就需要比較對(duì)象的大小
使用兩個(gè)接口中的任何一個(gè)來實(shí)現(xiàn): Comparable 或 Comparator
Comparable 接口的使用舉例 :
1. 像 String, 包裝類等實(shí)現(xiàn)了 Comparable 接口, 重寫了 `compareTo(obj)` 方法, 給出了比較兩個(gè)對(duì)象
2. 像 String, 包裝類重寫了`compareTo()`方法以后, 進(jìn)行了從小到大的排列
3. 重寫 `compareTo(obj)` 的規(guī)則:
如果當(dāng)前對(duì)象 this 等于形參對(duì)象 obj, 則返回為零
如果當(dāng)前對(duì)象 this 小于形參對(duì)象 obj, 則返回負(fù)整數(shù)
如果當(dāng)前對(duì)象 this 大于形參對(duì)象 obj, 則返回正整數(shù)
4. **對(duì)于自定義類來說**, 如果需要排序, 我們可以讓自定義類實(shí)現(xiàn) Comparable 接口, 重寫 `compareTo(obj)` 方法并在 `compareTO(obj)` 方法中指明如何排序
Demo:
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.util.Arrays;/** * 1) 說明: Java中的對(duì)象, 正常情況下, 只能進(jìn)行比較:==或!= 不能使用>或< * 但是在開發(fā)場景中, 我們需要對(duì)多個(gè)對(duì)象進(jìn)行排序, 言外之意, 就需要比較對(duì)象的大小 * 如何實(shí)現(xiàn)? 使用兩個(gè)接口中的任何一個(gè): Comparable 或 Comparator * 2) Comparable 接口的使用 * * @author 13roky * @date 2021-05-12 22:15 */public class CompareTest { /* Comparable 接口的使用舉例: 自然排序 1. 像 String, 包裝類等實(shí)現(xiàn)了 Comparable 接口, 重寫了 compareTo(obj) 方法, 給出了比較兩個(gè)對(duì)象 2. 像 String, 包裝類重寫了compareTo()方法以后,進(jìn)行了從小到大的排列 3. 重寫 compareTo(obj) 的規(guī)則: 如果當(dāng)前對(duì)象 this 等于形參對(duì)象 obj, 則返回為零 如果當(dāng)前對(duì)象 this 小于形參對(duì)象 obj, 則返回負(fù)整數(shù) 如果當(dāng)前對(duì)象 this 大于形參對(duì)象 obj, 則返回正整數(shù) 4. 對(duì)于自定義類來說, 如果需要排序, 我們可以讓自定義類實(shí)現(xiàn) Comparable 接口, 重寫compareTo(obj) 方法 在 compareTO(obj) 方法中知名如何排序 */ @Test public void test01(){ String[] arr = new String[]{"aa","cc","kk","mm","gg","jj","dd"}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); } @Test public void test02() { Goods[] arr = new Goods[4]; arr[0] = new Goods("lenovoMouse",34); arr[1] = new Goods("dellMouse",43); arr[2] = new Goods("xiaomiMouse",12); arr[3] = new Goods("huaweiMouse",65); arr[3] = new Goods("MicroSoftiMouse",12); // 根據(jù)arr所對(duì)應(yīng)類的CompareTo方法排序 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); }}
package com.broky.commonClass;/** * 商品類 實(shí)現(xiàn)Comparable方法 * * @author 13roky * @date 2021-05-12 22:42 */public class Goods implements Comparable { private String name; private double price; public Goods() { } public Goods(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Goods{" + "name='" + name + '\'' + ", price=" + price + '}'; } // 指明商品比較大小的方式:按照價(jià)格從低到高排序,再按照產(chǎn)品名稱從第到高排序 @Override public int compareTo(Object o) { if (o instanceof Goods) { // 方式一 Goods goods = (Goods) o; if (this.price > goods.price) { return 1; } else if (this.price < goods.price) { return -1; } else { // 字符串類型的本身就有 compareTo 方法 return this.name.compareTo(goods.name); // return -this.name.compareTo(goods.name); 加了負(fù)號(hào)變成了從高到低排 } // 方式二 //return Double.compare(this.price,goods.price); } throw new RuntimeException("傳入的數(shù)據(jù)類型不一致"); }}
5.2 Comparator 接口 定制排序
根據(jù)定制的規(guī)則進(jìn)行比較, Comparator屬于定制排序
當(dāng)元素的類型沒有實(shí)現(xiàn)java.lang.Comparable 接口而又不方便修改代碼,或者實(shí)現(xiàn)了java.lang.Comparable 接口的排序規(guī)則不適合當(dāng)前的操作, 那么可以使用 Compare(obj o1,obj o2)方法, 比較o1和o2的大小
說明 :
當(dāng)元素的類型沒有實(shí)現(xiàn)java.lang.Comparable接口而又不方便修改代碼, 或者實(shí)現(xiàn)了java.lang.Comparable接口的排序規(guī)則不適合當(dāng)前的操作,那么可以考慮使用 Comparator 的對(duì)象來排序,強(qiáng)行對(duì)多個(gè)對(duì)象進(jìn)行整體排序的比較。
使用 :
在
Arrays.sort()方法中使用匿名內(nèi)部類的方法實(shí)現(xiàn)定制排序 (詳情見Demo)
**Comparable 接口與 Comparator 的使用的對(duì)比 : **
Comparable 接口的方式一旦實(shí)現(xiàn),保證 Comparable 接口實(shí)現(xiàn)類的對(duì)象在任何位置都可以比較大小
Comparator 接口屬于臨時(shí)性的比較.
Demo :
package com.broky.commonClass;import org.junit.jupiter.api.Test;import java.util.Arrays;import java.util.Comparator;/** * 1) 說明: Java中的對(duì)象, 正常情況下, 只能進(jìn)行比較:==或!= 不能使用>或< * 但是在開發(fā)場景中, 我們需要對(duì)多個(gè)對(duì)象進(jìn)行排序, 言外之意, 就需要比較對(duì)象的大小 * 如何實(shí)現(xiàn)? 使用兩個(gè)接口中的任何一個(gè): Comparable 或 Comparator * 2) Comparable 接口與 Comparator 的使用的對(duì)比 * Comparable 接口的方式一旦實(shí)現(xiàn),保證 Comparable 接口實(shí)現(xiàn)類的對(duì)象在任何位置都可以比較大小 * Comparator 接口屬于臨時(shí)性的比較. * * @author 13roky * @date 2021-05-12 22:15 */public class CompareTest { /* Comparator 接口的使用: 定制排序 1. 背景 當(dāng)元素的類型沒有實(shí)現(xiàn)java.lang.Comparable 接口而又不方便修改代碼, 或者實(shí)現(xiàn)了java.lang.Comparable 接口的排序規(guī)則不適合當(dāng)前的操作 那么可以使用 Compare(obj o1,obj o2)方法, 比較o1和o2的大小 2. 重寫 Compare(obj o1,obj o2) 方法, 比較o1和o2的大小 如果方法返回正數(shù),則表示o1大于o2 如果方法返回負(fù)數(shù),則表示01小于02 如果方法返回0, 則表示相等 */ @Test public void test03(){ // test1 String[] arr = new String[]{"aa","cc","kk","mm","gg","jj","dd"}; // 從大到小排序 Arrays.sort(arr, new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof String && o2 instanceof String){ String s1 = (String) o1; String s2 = (String) o2; return -s1.compareTo(s2); } throw new RuntimeException("輸入的類型不一致"); } }); System.out.println(Arrays.toString(arr)); } @Test public void test04() { Goods[] arr = new Goods[5]; arr[0] = new Goods("lenovoMouse",34); arr[1] = new Goods("huaweiMouse",43); arr[2] = new Goods("xiaomiMouse",12); arr[3] = new Goods("huaweiMouse",65); arr[4] = new Goods("microSoftiMouse",12); Arrays.sort(arr,new Comparator(){ // 指明商品比較大小的方式:再按照產(chǎn)品名稱從第到高排序, 按照價(jià)格從高到低排序 @Override public int compare(Object o1, Object o2) { if (o1 instanceof Goods && o2 instanceof Goods){ Goods g1 = (Goods) o1; Goods g2 = (Goods) o2; if (g1.getName().equals(g2.getName())){ return -Double.compare(g1.getPrice(),g2.getPrice()); }else { return g1.getName().compareTo(g2.getName()); } } throw new RuntimeException("輸入的數(shù)據(jù)類型不一致"); } }); System.out.println(Arrays.toString(arr)); }}
6. System 類
System類代表系統(tǒng),系統(tǒng)級(jí)的很多屬性和控制方法都放置在該類的內(nèi)部。該類位于java.lang包。
由于該類的構(gòu)造器是private的,所以無法創(chuàng)建該類的對(duì)象,也就是無法實(shí) 例化該類。其內(nèi)部的成員變量和成員方法都是static的,所以也可以很方便 的進(jìn)行調(diào)用。
? 成員方法 ? native long currentTimeMillis():該方法的作用是返回當(dāng)前的計(jì)算機(jī)時(shí)間,時(shí)間的表達(dá)格式為當(dāng)前計(jì)算機(jī)時(shí) 間和GMT時(shí)間(格林威治時(shí)間)1970年1月1號(hào)0時(shí)0分0秒所差的毫秒數(shù)。? void exit(int status):該方法的作用是退出程序。其中status的值為0代表正常退出,非零代表 異常退出。使用該方法可以在圖形界面編程中實(shí)現(xiàn)程序的退出功能等。
成員變量 :
System類內(nèi)部包含in、out和err三個(gè)成員變量,分別代表標(biāo)準(zhǔn)輸入流 (鍵盤輸入),標(biāo)準(zhǔn)輸出流(顯示器)和標(biāo)準(zhǔn)錯(cuò)誤輸出流(顯示器)。
成員方法 :
native long currentTimeMillis():該方法的作用是返回當(dāng)前的計(jì)算機(jī)時(shí)間,時(shí)間的表達(dá)格式為當(dāng)前計(jì)算機(jī)時(shí) 間和GMT時(shí)間(格林威治時(shí)間)1970年1月1號(hào)0時(shí)0分0秒所差的毫秒數(shù)。
void exit(int status):該方法的作用是退出程序。其中status的值為0代表正常退出,非零代表 異常退出。使用該方法可以在圖形界面編程中實(shí)現(xiàn)程序的退出功能等。
void gc():該方法的作用是請求系統(tǒng)進(jìn)行垃圾回收。至于系統(tǒng)是否立刻回收,則 取決于系統(tǒng)中垃圾回收算法的實(shí)現(xiàn)以及系統(tǒng)執(zhí)行時(shí)的情況。
String getProperty(String key):該方法的作用是獲得系統(tǒng)中屬性名為key的屬性對(duì)應(yīng)的值。系統(tǒng)中常見 的屬性名以及屬性的作用如下表所示:

7. Math類
java.lang.Math提供了一系列靜態(tài)方法用于科學(xué)計(jì)算。
其方法的參數(shù)和返回 值類型一般為double型。
方法 :
abs 絕對(duì)值
acos,asin,atan,cos,sin,tan 三角函數(shù)
sqrt 平方根
pow(double a,doble b) a的b次冪
log 自然對(duì)數(shù)
exp e為底指數(shù)
max(double a,double b)
min(double a,double b)
random() 返回0.0到1.0的隨機(jī)數(shù)
long round(double a) double型數(shù)據(jù)a轉(zhuǎn)換為long型(四舍五入)
toDegrees(double angrad) 弧度—>角度
toRadians(double angdeg) 角度—>弧度
8. BigInteger 與 BigDecimal 類
用于操作較大的整數(shù)
8.1 BigInteger 類
類似于整形
說明 :
Integer類作為int的包裝類,能存儲(chǔ)的最大整型值為2 31-1,Long類也是有限的, 最大為2 63-1。如果要表示再大的整數(shù),不管是基本數(shù)據(jù)類型還是他們的包裝類 都無能為力,更不用說進(jìn)行運(yùn)算了。
java.math包的BigInteger可以表示不可變的任意精度的整數(shù)。BigInteger 提供 所有 Java 的基本整數(shù)操作符的對(duì)應(yīng)物,并提供 java.lang.Math 的所有相關(guān)方法。另外,BigInteger 還提供以下運(yùn)算:模算術(shù)、GCD 計(jì)算、質(zhì)數(shù)測試、素?cái)?shù)生成、 位操作以及一些其他操作。
構(gòu)造器 :
BigInteger(String val):根據(jù)字符串構(gòu)建 BigInteger 對(duì)象
常用方法 :
public BigInteger abs():返回此 BigInteger 的絕對(duì)值的 BigInteger。
BigInteger add(BigInteger val) :返回其值為 (this + val) 的 BigInteger
BigInteger subtract(BigInteger val) :返回其值為 (this - val) 的 BigInteger
BigInteger multiply(BigInteger val) :返回其值為 (this * val) 的 BigInteger
BigInteger divide(BigInteger val) :返回其值為 (this / val) 的 BigInteger。整數(shù) 相除只保留整數(shù)部分。
BigInteger remainder(BigInteger val) :返回其值為 (this % val) 的 BigInteger。
BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的兩個(gè) BigInteger 的數(shù)組。
BigInteger pow(int exponent) :返回其值為 (thisexponent) 的 BigInteger。
8.2 BigDecimal 類
類似于浮點(diǎn)型
說明 :
一般的Float類和Double類可以用來做科學(xué)計(jì)算或工程計(jì)算,但在商業(yè)計(jì)算中, 要求數(shù)字精度比較高,故用到j(luò)ava.math.BigDecimal類。
BigDecimal 類支持不可變的、任意精度的有符號(hào)十進(jìn)制定點(diǎn)數(shù)。
構(gòu)造器 :
public BigDecimal(double val)
public BigDecimal(String val)
常用方法 :
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
Demo :
package com.broky.commonClass;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author 13roky
* @date 2021-05-13 12:56
*/
public class OtherClassTest {
@Test
public void testBigInteger() {
BigInteger bi = new BigInteger("12433241123");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// BigDecimal.ROUND_HALF_UP 四舍五入
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}
}
粉絲福利:Java從入門到入土學(xué)習(xí)路線圖
??????

??長按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
