適合有其他語言基礎想快速入門JavaSE的。用的資料是 Java入門基礎視頻教程 ,從中摘取了筆者認為與其他語言不同或需要重點學習的內容
常用API與日期類只需要有印象即可,用到了再來這查
day04 常用API
一、StringBuilder類
- StringBuilder代表可變字符串對象,相當于是一個容器,它里面的字符串是可以改變的,就是用來操作字符串的。
- 好處:StringBuilder比String更合適做字符串的修改操作,效率更高,代碼也更加簡潔。
public class Test{public static void main(String[] args){StringBuilder sb = new StringBuilder("itehima");//1.拼接內容sb.append(12);sb.append("黑馬");sb.append(true);//2.append方法,支持臨時編程sb.append(666).append("黑馬2").append(666);System.out.println(sb); //打印:12黑馬666黑馬2666//3.反轉操作sb.reverse();System.out.println(sb); //打印:6662馬黑666馬黑21//4.返回字符串的長度System.out.println(sb.length());//5.StringBuilder還可以轉換為字符串String s = sb.toString();System.out.println(s); //打印:6662馬黑666馬黑21}
}
直接使用String拼接(s = s + "abc"
)100萬次,等了1分鐘,還沒結束,我等不下去了;但是使用StringBuilder(sb.append("abc")
)做拼接,不到1秒鐘出結果了。
二、StringJoiner類
是因為我們前面使用StringBuilder拼接字符串的時,代碼寫起來還是有一點麻煩,而StringJoiner號稱是拼接神器,不僅效率高,而且代碼簡潔。
public class Test{public static void main(String[] args){StringJoiner s = new StringJoiner(",");s.add("java1");s.add("java2");s.add("java3");System.out.println(s); //結果為: java1,java2,java3//參數1:間隔符//參數2:開頭//參數3:結尾StringJoiner s1 = new StringJoiner(",","[","]");s1.add("java1");s1.add("java2");s1.add("java3");System.out.println(s1); //結果為: [java1,java2,java3]}
}
三、Math類
該類提供了很多個進行數學運算的方法,如求絕對值,求最大值,四舍五入等
public class MathTest {public static void main(String[] args) {// 目標:了解下Math類提供的常見方法。// 1、public static int abs(int a):取絕對值(拿到的結果一定是正數)// public static double abs(double a)System.out.println(Math.abs(-12)); // 12System.out.println(Math.abs(123)); // 123System.out.println(Math.abs(-3.14)); // 3.14// 2、public static double ceil(double a): 向上取整System.out.println(Math.ceil(4.0000001)); // 5.0System.out.println(Math.ceil(4.0)); // 4.0// 3、public static double floor(double a): 向下取整System.out.println(Math.floor(4.999999)); // 4.0System.out.println(Math.floor(4.0)); // 4.0// 4、public static long round(double a):四舍五入System.out.println(Math.round(3.4999)); // 3System.out.println(Math.round(3.50001)); // 4// 5、public static int max(int a, int b):取較大值// public static int min(int a, int b):取較小值System.out.println(Math.max(10, 20)); // 20System.out.println(Math.min(10, 20)); // 10// 6、 public static double pow(double a, double b):取次方System.out.println(Math.pow(2, 3)); // 2的3次方 8.0System.out.println(Math.pow(3, 2)); // 3的2次方 9.0// 7、public static double random(): 取隨機數 [0.0 , 1.0) (包前不包后)System.out.println(Math.random());}
}
四、System類
這是系統類,提供了一些獲取系統數據的方法。比如獲取系統時間。
public class SystemTest {public static void main(String[] args) {// 1、public static void exit(int status):// 終止當前運行的Java虛擬機。// 該參數用作狀態代碼; 按照慣例,非零狀態代碼表示異常終止。System.exit(0); // 人為的終止虛擬機。(不要使用)// 2、public static long currentTimeMillis():// 獲取當前系統的時間// 返回的是long類型的時間毫秒值:指的是從1970-1-1 0:0:0開始走到此刻的總的毫秒值,1s = 1000mslong time = System.currentTimeMillis();System.out.println(time);for (int i = 0; i < 1000000; i++) {System.out.println("輸出了:" + i);}long time2 = System.currentTimeMillis();System.out.println((time2 - time) / 1000.0 + "s");}
}
五、Runtime類
再學習一個Java的運行時類,叫Runtime類。這個類可以用來獲取JVM的一些信息,也可以用這個類去執行其他的程序。
public class RuntimeTest {public static void main(String[] args) throws IOException, InterruptedException {// 1、public static Runtime getRuntime() 返回與當前Java應用程序關聯的運行時對象。Runtime r = Runtime.getRuntime();// 2、public void exit(int status) 終止當前運行的虛擬機,該參數用作狀態代碼; 按照慣例,非零狀態代碼表示異常終止。// r.exit(0);// 3、public int availableProcessors(): 獲取虛擬機能夠使用的處理器數。System.out.println(r.availableProcessors());// 4、public long totalMemory() 返回Java虛擬機中的內存總量。System.out.println(r.totalMemory()/1024.0/1024.0 + "MB"); // 1024 = 1K 1024 * 1024 = 1M// 5、public long freeMemory() 返回Java虛擬機中的可用內存量System.out.println(r.freeMemory()/1024.0/1024.0 + "MB");// 6、public Process exec(String command) 啟動某個程序,并返回代表該程序的對象。// r.exec("D:\\soft\\XMind\\XMind.exe");Process p = r.exec("QQ");Thread.sleep(5000); // 讓程序在這里暫停5s后繼續往下走!!p.destroy(); // 銷毀!關閉程序!}
}
六、BigDecimal類
接下來我們學習的這個類叫BigDecimal,至于它是干什么用的,我們先不說。我們先看一段代碼,看這個代碼有什么問題?再說BigDeimal這個類是干什么用的,這樣會更好理解一些。
public class Test {public static void main(String[] args) {System.out.println(0.1 + 0.2);System.out.println(1.0 - 0.32);System.out.println(1.015 * 100);System.out.println(1.301 / 100);}
}
運行以上代碼,我們會發現,結果并和我們想看到的不太一樣。
0.30000000000000004
0.6799999999999999
101.49999999999999
0.013009999999999999
為了解決浮點型運算時的精度損失的問題,Java給我們提供了BigDecimal類,它提供了一些方法可以對數據進行四則運算,而且不丟失精度,同時還可以保留指定的小數位。
public class Test2 {public static void main(String[] args) {// 目標:掌握BigDecimal進行精確運算的方案。double a = 0.1;double b = 0.2;// 1、把浮點型數據封裝成BigDecimal對象,再來參與運算。// a、public BigDecimal(double val) 得到的BigDecimal對象是無法精確計算浮點型數據的。 注意:不推薦使用這個,// b、public BigDecimal(String val) 得到的BigDecimal對象是可以精確計算浮點型數據的。 可以使用。// c、public static BigDecimal valueOf(double val): 通過這個靜態方法得到的BigDecimal對象是可以精確運算的。是最好的方案。BigDecimal a1 = BigDecimal.valueOf(a);BigDecimal b1 = BigDecimal.valueOf(b);// 2、public BigDecimal add(BigDecimal augend): 加法BigDecimal c1 = a1.add(b1);System.out.println(c1);// 3、public BigDecimal subtract(BigDecimal augend): 減法BigDecimal c2 = a1.subtract(b1);System.out.println(c2);// 4、public BigDecimal multiply(BigDecimal augend): 乘法BigDecimal c3 = a1.multiply(b1);System.out.println(c3);// 5、public BigDecimal divide(BigDecimal b): 除法BigDecimal c4 = a1.divide(b1);System.out.println(c4);// BigDecimal d1 = BigDecimal.valueOf(0.1);
// BigDecimal d2 = BigDecimal.valueOf(0.3);
// BigDecimal d3 = d1.divide(d2);
// System.out.println(d3);// 6、public BigDecimal divide(另一個BigDecimal對象,精確幾位,舍入模式) : 除法,可以設置精確幾位。BigDecimal d1 = BigDecimal.valueOf(0.1);BigDecimal d2 = BigDecimal.valueOf(0.3);BigDecimal d3 = d1.divide(d2, 2, RoundingMode.HALF_UP); // 0.33System.out.println(d3);// 7、public double doubleValue() : 把BigDecimal對象又轉換成double類型的數據。//print(d3);//print(c1);double db1 = d3.doubleValue();double db2 = c1.doubleValue();print(db1);print(db2);}public static void print(double a){System.out.println(a);}
}
五、Date類
Java中是由這個類的對象用來表示日期或者時間。
Date對象記錄的時間是用毫秒值來表示的。Java語言規定,1970年1月1日0時0分0秒認為是時間的起點,此時記作0,那么1000(1秒=1000毫秒)就表示1970年1月1日0時0分1秒,依次內推。
public class Test1Date {public static void main(String[] args) {// 目標:掌握Date日期類的使用。// 1、創建一個Date的對象:代表系統當前時間信息的。Date d = new Date();System.out.println(d); // Fri Sep 12 09:24:27 CST 2025// 2、拿到時間毫秒值。long time = d.getTime();System.out.println(time); // 1757640267698// 3、把時間毫秒值轉換成日期對象: 2s之后的時間是多少。time += 2 * 1000;Date d2 = new Date(time);System.out.println(d2); // Fri Sep 12 09:24:29 CST 2025// 4、直接把日期對象的時間通過setTime方法進行修改Date d3 = new Date();d3.setTime(time);System.out.println(d3); // Fri Sep 12 09:24:29 CST 2025}
}
六、SimpleDateFormat類
接下來我們學習的SimpleDateFormat類就可以轉換Date對象表示日期時間的顯示格式。
- 我們把Date對象轉換為指定格式的日期字符串這個操作,叫做日期格式化,
- 反過來把指定格式的日期符串轉換為Date對象的操作,叫做日期解析。
注意:創建SimpleDateFormat對象時,在構造方法的參數位置傳遞日期格式,而日期格式是由一些特定的字母拼接而來的。我們需要記住常用的幾種日期/時間格式
字母 表示含義
yyyy 年
MM 月
dd 日
HH 時
mm 分
ss 秒
SSS 毫秒"2022年12月12日" 的格式是 "yyyy年MM月dd日"
"2022-12-12 12:12:12" 的格式是 "yyyy-MM-dd HH:mm:ss"
按照上面的格式可以任意拼接,但是字母不能寫錯
public class Test2SimpleDateFormat {public static void main(String[] args) throws ParseException {// 目標:掌握SimpleDateFormat的使用。// 1、準備一些時間Date d = new Date();System.out.println(d); // Fri Sep 12 09:37:15 CST 2025long time = d.getTime();System.out.println(time); // 1757641035548// 2、格式化日期對象,和時間 毫秒值。SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");String rs = sdf.format(d);String rs2 = sdf.format(time);System.out.println(rs); // 2025年09月12日 09:37:15 周五 上午System.out.println(rs2); // 2025年09月12日 09:37:15 周五 上午System.out.println("----------------------------------------------");// 目標:掌握SimpleDateFormat解析字符串時間 成為日期對象。String dateStr = "2022-12-12 12:12:11";// 1、創建簡單日期格式化對象 , 指定的時間格式必須與被解析的時間格式一模一樣,否則程序會出bug.SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d2 = sdf2.parse(dateStr);System.out.println(d2); // Mon Dec 12 12:12:11 CST 2022}
}
七、Calendar類
我們再學習一個和日期相關的類,它是Calendar類。Calendar類表示日歷,它提供了一些比Date類更好用的方法。
比如下面的案例(需求:將2023年09月10日增加一個月),用Date類就不太好做,而用Calendar就特別方便。因為Calendar類提供了方法可以直接對日歷中的年、月、日、時、分、秒等進行運算。
Calendar
- 代表的是系統此刻時間對應的日歷。
- 通過它可以單獨獲取、修改時間中的年、月、日、時、分、秒等。
注意:calendar是可變對象,一旦修改后其對象本身表示的時間將產生變化。
public class Test4Calendar {public static void main(String[] args) {// 目標:掌握Calendar的使用和特點。// 1、得到系統此刻時間對應的日歷對象。Calendar now = Calendar.getInstance();System.out.println(now); // java.util.GregorianCalendar[time=1757641127867,...,YEAR=2025,MONTH=8,WEEK_OF_YEAR=37,WEEK_OF_MONTH=2,DAY_OF_MONTH=12,DAY_OF_YEAR=255,...// 2、獲取日歷中的某個信息int year = now.get(Calendar.YEAR);System.out.println(year); // 2025int days = now.get(Calendar.DAY_OF_YEAR);System.out.println(days); // 255// 3、拿到日歷中記錄的日期對象。Date d = now.getTime();System.out.println(d); // Fri Sep 12 09:38:47 CST 2025// 4、拿到時間毫秒值long time = now.getTimeInMillis();System.out.println(time); // 1757641127867// 5、修改日歷中的某個信息now.set(Calendar.MONTH, 9); // 修改月份成為10月份。now.set(Calendar.DAY_OF_YEAR, 125); // 修改成一年中的第125天。System.out.println(now); // java.util.GregorianCalendar[time=?,...,YEAR=2025,MONTH=9,WEEK_OF_YEAR=37,WEEK_OF_MONTH=2,DAY_OF_MONTH=12,DAY_OF_YEAR=125,...// 6、為某個信息增加或者減少多少now.add(Calendar.DAY_OF_YEAR, 100);now.add(Calendar.DAY_OF_YEAR, -10);now.add(Calendar.DAY_OF_MONTH, 6);now.add(Calendar.HOUR, 12);now.set(2026, 11, 22);System.out.println(now); // java.util.GregorianCalendar[time=?,...,YEAR=2026,MONTH=11,WEEK_OF_YEAR=32,WEEK_OF_MONTH=2,DAY_OF_MONTH=22,DAY_OF_YEAR=221,...}
}
八、為什么JDK8要新增日期類
public class Test {public static void main(String[] args) {// 傳統的時間類(Date、SimpleDateFormat、Calendar)存在如下問題:// 1、設計不合理,使用不方便,很多都被淘汰了。Date d = new Date();//System.out.println(d.getYear()); // 125(+1900=2025)Calendar c = Calendar.getInstance();int year = c.get(Calendar.YEAR);System.out.println(year); // 2025// 2、都是可變對象,修改后會丟失最開始的時間信息。// 3、線程不安全。// 4、不能精確到納秒,只能精確到毫秒。// 1秒 = 1000毫秒// 1毫秒 = 1000微妙// 1微妙 = 1000納秒}
}
九、JDK8日期、時間、日期時間
JDK8新增的日期類分得更細致一些,比如表示年月日用LocalDate類、表示時間秒用LocalTime類、而表示年月日時分秒用LocalDateTime類等;除了這些類還提供了對時區、時間間隔進行操作的類等。它們幾乎把對日期/時間的所有操作都通過了API方法,用起來特別方便。
先學習表示日期、時間、日期時間的類;有LocalDate、LocalTime、以及LocalDateTime類。仔細閱讀代碼,你會發現這三個類的用法套路都是一樣的。
public class Test1_LocalDate {public static void main(String[] args) {// 0、獲取本地日期對象(不可變對象)LocalDate ld = LocalDate.now(); // 年 月 日System.out.println(ld);// 1、獲取日期對象中的信息int year = ld.getYear(); // 年int month = ld.getMonthValue(); // 月(1-12)int day = ld.getDayOfMonth(); // 日int dayOfYear = ld.getDayOfYear(); // 一年中的第幾天int dayOfWeek = ld.getDayOfWeek().getValue(); // 星期幾System.out.println(year);System.out.println(day);System.out.println(dayOfWeek);// 2、直接修改某個信息: withYear、withMonth、withDayOfMonth、withDayOfYearLocalDate ld2 = ld.withYear(2099);LocalDate ld3 = ld.withMonth(12);System.out.println(ld2);System.out.println(ld3);System.out.println(ld);// 3、把某個信息加多少: plusYears、plusMonths、plusDays、plusWeeksLocalDate ld4 = ld.plusYears(2);LocalDate ld5 = ld.plusMonths(2);// 4、把某個信息減多少:minusYears、minusMonths、minusDays、minusWeeksLocalDate ld6 = ld.minusYears(2);LocalDate ld7 = ld.minusMonths(2);// 5、獲取指定日期的LocalDate對象: public static LocalDate of(int year, int month, int dayOfMonth)LocalDate ld8 = LocalDate.of(2099, 12, 12);LocalDate ld9 = LocalDate.of(2099, 12, 12);// 6、判斷2個日期對象,是否相等,在前還是在后: equals isBefore isAfterSystem.out.println(ld8.equals(ld9));// trueSystem.out.println(ld8.isAfter(ld)); // trueSystem.out.println(ld8.isBefore(ld)); // false}
}
public class Test2_LocalTime {public static void main(String[] args) {// 0、獲取本地時間對象LocalTime lt = LocalTime.now(); // 時 分 秒 納秒 不可變的System.out.println(lt);// 1、獲取時間中的信息int hour = lt.getHour(); //時int minute = lt.getMinute(); //分int second = lt.getSecond(); //秒int nano = lt.getNano(); //納秒// 2、修改時間:withHour、withMinute、withSecond、withNanoLocalTime lt3 = lt.withHour(10);LocalTime lt4 = lt.withMinute(10);LocalTime lt5 = lt.withSecond(10);LocalTime lt6 = lt.withNano(10);// 3、加多少:plusHours、plusMinutes、plusSeconds、plusNanosLocalTime lt7 = lt.plusHours(10);LocalTime lt8 = lt.plusMinutes(10);LocalTime lt9 = lt.plusSeconds(10);LocalTime lt10 = lt.plusNanos(10);// 4、減多少:minusHours、minusMinutes、minusSeconds、minusNanosLocalTime lt11 = lt.minusHours(10);LocalTime lt12 = lt.minusMinutes(10);LocalTime lt13 = lt.minusSeconds(10);LocalTime lt14 = lt.minusNanos(10);// 5、獲取指定時間的LocalTime對象:// public static LocalTime of(int hour, int minute, int second)LocalTime lt15 = LocalTime.of(12, 12, 12);LocalTime lt16 = LocalTime.of(12, 12, 12);// 6、判斷2個時間對象,是否相等,在前還是在后: equals isBefore isAfterSystem.out.println(lt15.equals(lt16)); // trueSystem.out.println(lt15.isAfter(lt)); // falseSystem.out.println(lt15.isBefore(lt)); // true}
}
public class Test3_LocalDateTime {public static void main(String[] args) {// 0、獲取本地日期和時間對象。LocalDateTime ldt = LocalDateTime.now(); // 年 月 日 時 分 秒 納秒System.out.println(ldt);// 1、可以獲取日期和時間的全部信息int year = ldt.getYear(); // 年int month = ldt.getMonthValue(); // 月int day = ldt.getDayOfMonth(); // 日int dayOfYear = ldt.getDayOfYear(); // 一年中的第幾天int dayOfWeek = ldt.getDayOfWeek().getValue(); // 獲取是周幾int hour = ldt.getHour(); //時int minute = ldt.getMinute(); //分int second = ldt.getSecond(); //秒int nano = ldt.getNano(); //納秒// 2、修改時間信息:// withYear withMonth withDayOfMonth withDayOfYear withHour// withMinute withSecond withNanoLocalDateTime ldt2 = ldt.withYear(2029);LocalDateTime ldt3 = ldt.withMinute(59);// 3、加多少:// plusYears plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanosLocalDateTime ldt4 = ldt.plusYears(2);LocalDateTime ldt5 = ldt.plusMinutes(3);// 4、減多少:// minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanosLocalDateTime ldt6 = ldt.minusYears(2);LocalDateTime ldt7 = ldt.minusMinutes(3);// 5、獲取指定日期和時間的LocalDateTime對象:// public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour,// int minute, int second, int nanoOfSecond)LocalDateTime ldt8 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);LocalDateTime ldt9 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);// 6、 判斷2個日期、時間對象,是否相等,在前還是在后: equals、isBefore、isAfterSystem.out.println(ldt9.equals(ldt8));System.out.println(ldt9.isAfter(ldt));System.out.println(ldt9.isBefore(ldt));// 7、可以把LocalDateTime轉換成LocalDate和LocalTime// public LocalDate toLocalDate()// public LocalTime toLocalTime()// public static LocalDateTime of(LocalDate date, LocalTime time)LocalDate ld = ldt.toLocalDate();LocalTime lt = ldt.toLocalTime();LocalDateTime ldt10 = LocalDateTime.of(ld, lt);}
}
十、JDK8日期(時區)
接著,我們學習代表時區的兩個類。由于世界各個國家與地區的經度不同,各地區的時間也有所不同,因此會劃分為不同的時區。每一個時區的時間也不太一樣。
public class Test4_ZoneId_ZonedDateTime {public static void main(String[] args) {// 目標:了解時區和帶時區的時間。// 1、ZoneId的常見方法:// public static ZoneId systemDefault(): 獲取系統默認的時區ZoneId zoneId = ZoneId.systemDefault();System.out.println(zoneId.getId());System.out.println(zoneId);// public static Set<String> getAvailableZoneIds(): 獲取Java支持的全部時區IdSystem.out.println(ZoneId.getAvailableZoneIds());// public static ZoneId of(String zoneId) : 把某個時區id封裝成ZoneId對象。ZoneId zoneId1 = ZoneId.of("America/New_York");// 2、ZonedDateTime:帶時區的時間。// public static ZonedDateTime now(ZoneId zone): 獲取某個時區的ZonedDateTime對象。ZonedDateTime now = ZonedDateTime.now(zoneId1);System.out.println(now);// 世界標準時間了ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());System.out.println(now1);// public static ZonedDateTime now():獲取系統默認時區的ZonedDateTime對象ZonedDateTime now2 = ZonedDateTime.now();System.out.println(now2);// Calendar instance = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));}
}
十一、JDK8日期(Instant類)
接下來,我們來學習Instant這個類。通過獲取Instant的對象可以拿到此刻的時間,該時間由兩部分組成:從1970-01-01 00:00:00 開始走到此刻的總秒數+不夠1秒的納秒數。
可以用來獲取當前時間,也可以對時間進行加、減、獲取等操作。
作用:可以用來記錄代碼的執行時間,或用于記錄用戶操作某個事件的時間點。
public class Test5_Instant {public static void main(String[] args) {// 1、創建Instant的對象,獲取此刻時間信息Instant now = Instant.now(); // 不可變對象// 2、獲取總秒數long second = now.getEpochSecond();System.out.println(second);// 3、不夠1秒的納秒數int nano = now.getNano();System.out.println(nano);System.out.println(now);Instant instant = now.plusNanos(111);// Instant對象的作用:做代碼的性能分析,或者記錄用戶的操作時間點Instant now1 = Instant.now();// 代碼執行。。。。Instant now2 = Instant.now();LocalDateTime l = LocalDateTime.now();}
}
十二、JDK8日期(格式化器)
它可以從來對日期進行格式化和解析。它代替了原來的SimpleDateFormat類(線程不安全)。
DateTimeFormatter:格式化器,用于時間的格式化、解析(線程安全)。
public class Test6_DateTimeFormatter {public static void main(String[] args) {// 1、創建一個日期時間格式化器對象出來。DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");// 2、對時間進行格式化LocalDateTime now = LocalDateTime.now();System.out.println(now); // 2025-09-12T22:09:18.875713String rs = formatter.format(now); // 正向格式化System.out.println(rs); // 2025年09月12日 22:09:18// 3、格式化時間,其實還有一種方案。String rs2 = now.format(formatter); // 反向格式化System.out.println(rs2); // 2025年09月12日 22:09:18// 4、解析時間:解析時間一般使用LocalDateTime提供的解析方法來解析。String dateStr = "2029年12月12日 12:12:11";LocalDateTime ldt = LocalDateTime.parse(dateStr, formatter);System.out.println(ldt); // 2029-12-12T12:12:11}
}
十三、JDK8日期(Period類)
除以了上新增的類,JDK8還補充了兩個類,一個叫Period類、一個叫Duration類;這兩個類可以用來對計算兩個時間點的時間間隔。
其中Period用來計算日期間隔(年、月、日),Duration用來計算時間間隔(時、分、秒、納秒)
先來演示Period類的用法,它的方法如下圖所示。可以用來計算兩個日期之間相隔的年、相隔的月、相隔的日。只能兩個計算LocalDate對象之間的間隔
/*** 目標:掌握Period的作用:計算機兩個日期相差的年數,月數、天數。*/
public class Test7_Period {public static void main(String[] args) {LocalDate start = LocalDate.of(2029, 8, 10);LocalDate end = LocalDate.of(2029, 12, 15);// 1、創建Period對象,封裝兩個日期對象。Period period = Period.between(start, end);// 2、通過period對象獲取兩個日期對象相差的信息。System.out.println(period.getYears());System.out.println(period.getMonths());System.out.println(period.getDays());}
}
十四、JDK8日期(Duration類)
接下來,我們學習Duration類。它是用來表示兩個時間對象的時間間隔。可以用于計算兩個時間對象相差的天數、小時數、分數、秒數、納秒數;支持LocalTime、LocalDateTime、Instant等時間
public class Test8_Duration {public static void main(String[] args) {LocalDateTime start = LocalDateTime.of(2025, 11, 11, 11, 10, 10);LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11, 11);// 1、得到Duration對象Duration duration = Duration.between(start, end);// 2、獲取兩個時間對象間隔的信息System.out.println(duration.toDays());// 間隔多少天System.out.println(duration.toHours());// 間隔多少小時System.out.println(duration.toMinutes());// 間隔多少分System.out.println(duration.toSeconds());// 間隔多少秒System.out.println(duration.toMillis());// 間隔多少毫秒System.out.println(duration.toNanos());// 間隔多少納秒}
}
day05 算法和數據結構
一、Arrays類
1.1 Arrays基本使用
Arrays是操作數組的工具類,它可以很方便的對數組中的元素進行遍歷、拷貝、排序等操作。
public class ArraysTest1 {public static void main(String[] args) {// 1、public static String toString(類型[] arr): 返回數組的內容int[] arr = {10, 20, 30, 40, 50, 60};System.out.println(Arrays.toString(arr));// 2、public static 類型[] copyOfRange(類型[] arr, 起始索引, 結束索引) :拷貝數組(指定范圍,包前不包后)int[] arr2 = Arrays.copyOfRange(arr, 1, 4);System.out.println(Arrays.toString(arr2));// 3、public static copyOf(類型[] arr, int newLength):拷貝數組,可以指定新數組的長度。int[] arr3 = Arrays.copyOf(arr, 10);System.out.println(Arrays.toString(arr3));// 4、public static setAll(double[] array, IntToDoubleFunction generator):把數組中的原數據改為新數據又存進去。double[] prices = {99.8, 128, 100};// 0 1 2// 把所有的價格都打八折,然后又存進去。// 匿名內部類Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;}});System.out.println(Arrays.toString(prices));// 5、public static void sort(類型[] arr):對數組進行排序(默認是升序排序)Arrays.sort(prices);System.out.println(Arrays.toString(prices));}
}
IntToDoubleFunction
是Java8新引入的函數式接口,它的作用是:
- 接受一個 int 參數(在這里是數組索引)(在這個例子中,value 參數實際上是數組索引(0, 1, 2…),不是數組的原始值。)
- 返回一個 double 值(新的數組元素值)
1.2 Arrays操作對象數組
剛才我們使用Arrays操作數組時,數組中存儲存儲的元素是int類型、double類型,是可以直接排序的,而且默認是升序排列。
如果數組中存儲的元素類型是自定義的對象,如何排序呢?接下來,我們就學習一下Arrays如何對對象數組進行排序。
public class Student implements Comparable<Student>{private String name;private double height;private int age;public Student(String name, double height, int age) {this.name = name;this.height = height;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", height=" + height +", age=" + age +'}';}
}
然后再寫一個測試類,往數組中存儲4個學生對象,代碼如下Arrays.sort(students);
。此時,運行代碼你會發現是會報錯ClassCastException
的。
public class ArraysTest2 {public static void main(String[] args) {// 目標:掌握如何對數組中的對象進行排序。Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊寶", 167.5, 24);// 1、public static void sort(類型[] arr):對數組進行排序。Arrays.sort(students);System.out.println(Arrays.toString(students));}
}
為了讓Arrays知道按照什么規則排序,我們有如下的兩種辦法。
排序方式1:讓Student類實現Comparable接口,同時重寫compareTo方法。Arrays的sort方法底層會根據compareTo方法的返回值是正數、負數、還是0來確定誰大、誰小、誰相等。代碼如下:
public class Student implements Comparable<Student>{private String name;private double height;private int age;//...get、set、空參數構造方法、有參數構造方法...自己補全// 指定比較規則// this o@Overridepublic int compareTo(Student o) {// 約定1:認為左邊對象 大于 右邊對象 請您返回正整數// 約定2:認為左邊對象 小于 右邊對象 請您返回負整數// 約定3:認為左邊對象 等于 右邊對象 請您一定返回0/* if(this.age > o.age){return 1;}else if(this.age < o.age){return -1;}return 0;*///上面的if語句,也可以簡化為下面的一行代碼return this.age - o.age; // 按照年齡升序排列// return o.age - this.age; // 按照年齡降序排列}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", height=" + height +", age=" + age +'}';}
}
此時 Arrays.sort(students);
就不會報錯了
**排序方式2:**在調用Arrays.sort(數組,Comparator比較器);
時,除了傳遞數組之外,傳遞一個Comparator比較器對象。Arrays的sort方法底層會根據Comparator比較器對象的compare方法方法的返回值是正數、負數、還是0來確定誰大、誰小、誰相等。代碼如下
public class ArraysTest2 {public static void main(String[] args) {// 目標:掌握如何對數組中的對象進行排序。Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊寶", 167.5, 24);// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)// 參數一:需要排序的數組// 參數二:Comparator比較器對象(用來制定對象的比較規則)Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 制定比較規則了:左邊對象 o1 右邊對象 o2// 約定1:認為左邊對象 大于 右邊對象 請您返回正整數// 約定2:認為左邊對象 小于 右邊對象 請您返回負整數// 約定3:認為左邊對象 等于 右邊對象 請您一定返回0
// if(o1.getHeight() > o2.getHeight()){
// return 1;
// }else if(o1.getHeight() < o2.getHeight()){
// return -1;
// }
// return 0; // 升序return Double.compare(o1.getHeight(), o2.getHeight()); // 升序// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序}});System.out.println(Arrays.toString(students));}
}
注意這里使用Double.compare(double d1, double d2)
,因為這個是兩個double做減法,前面說過會有精度損失的問題,所以不能直接相減。而如果是兩個int,直接做減法就好了。
當d1>d2時,Double.compare(double d1, double d2)
會返回正數(因為內部是return d1 - d2
),此時Comparator.compare()
會返回正數,則o1會排在o2后面(因為默認是升序)
二、Lambda表達式
接下來,我們學習一個JDK8新增的一種語法形式,叫做Lambda表達式。作用:用于簡化匿名內部類代碼的書寫。
2.1 Lambda表達式基本使用
按照下面的格式來編寫Lamdba。
(被重寫方法的形參列表) -> {被重寫方法的方法體代碼;
}
需要給說明一下的是,在使用Lambda表達式之前,必須先有一個接口,而且接口中只能有一個抽象方法。(注意:不能是抽象類,只能是接口)
像這樣的接口,我們稱之為函數式接口(接口中只有一個抽象方法),只有基于函數式接口的匿名內部類才能被Lambda表達式簡化。
public interface Swimming{void swim();
}
public class LambdaTest1 {public static void main(String[] args) {// 目標:認識Lambda表達式.//1.創建一個Swimming接口的匿名內部類對象Swimming s = new Swimming(){@Overridepublic void swim() {System.out.println("學生快樂的游泳~~~~");}};s.swim();//2.使用Lambda表達式對Swimming接口的匿名內部類進行簡化Swimming s1 = () -> {System.out.println("學生快樂的游泳~~~~");};s1.swim();}
}
好的,我們現在已經知道Lamdba表達式可以簡化基于函數式接口的匿名內部類的書寫。接下來,我們可以把剛才使用Arrays方法時的代碼,使用Lambda表達式簡化一下了。
public class LambdaTest2 {public static void main(String[] args) {// 目標:使用Lambda簡化函數式接口。double[] prices = {99.8, 128, 100};//1.把所有元素*0.8: 先用匿名內部類寫法Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;}});//2.把所有元素*0.8: 改用Lamdba表達式寫法Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8;});System.out.println(Arrays.toString(prices));System.out.println("-----------------------------------------------");Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊寶", 167.5, 24);//3.對數組中的元素按照年齡升序排列: 先用匿名內部類寫法Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序}});//4.對數組中的元素按照年齡升序排列: 改用Lambda寫法Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});System.out.println(Arrays.toString(students));}
}
Java編譯器通過目標類型推導(Target Type Inference)來確定lambda表達式對應的函數式接口。(1)編譯器看到Arrays.sort(students, lambda表達式)
。(2)查看Arrays.sort方法簽名,發現第二個參數期望Comparator<Student>
類型
2.2 Lambda表達式省略規則
Java覺得代碼還不夠簡單,于是還提供了Lamdba表達式的幾種簡化寫法。具體的簡化規則如下
1.Lambda的標準格式(參數類型1 參數名1, 參數類型2 參數名2)->{...方法體的代碼...return 返回值;}2.在標準格式的基礎上()中的參數類型可以直接省略(參數名1, 參數名2)->{...方法體的代碼...return 返回值;}3.如果{}總的語句只有一條語句,則{}可以省略、return關鍵字、以及最后的“;”都可以省略(參數名1, 參數名2)-> 結果4.如果()里面只有一個參數,則()可以省略(參數名)->結果
接下來從匿名內部類開始、到Lambda標準格式、再到Lambda簡化格式,一步一步來簡化一下。
public class LambdaTest2 {public static void main(String[] args) {// 目標:使用Lambda簡化函數式接口。double[] prices = {99.8, 128, 100};//1.對數組中的每一個元素*0.8: 匿名內部類寫法Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;}});//2.需求:對數組中的每一個元素*0.8,使用Lambda表達式標準寫法Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8;});//3.使用Lambda表達式簡化格式1——省略參數類型Arrays.setAll(prices, (value) -> {return prices[value] * 0.8;});//4.使用Lambda表達式簡化格式2——省略()Arrays.setAll(prices, value -> {return prices[value] * 0.8;});//5.使用Lambda表達式簡化格式3——省略{}Arrays.setAll(prices, value -> prices[value] * 0.8 );System.out.println(Arrays.toString(prices));System.out.println("------------------------------------Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊寶", 167.5, 24);//1.使用匿名內部類Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序}});//2.使用Lambda表達式表達式——標準格式Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});//3.使用Lambda表達式表達式——省略參數類型Arrays.sort(students, ( o1, o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});//4.使用Lambda表達式表達式——省略{}Arrays.sort(students, ( o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()));System.out.println(Arrays.toString(students));}
}
三、JDK8新特性(方法引用)
接下來我們學習JDK8的另一個新特性,叫做方法引用。我們知道Lambda是用來簡化匿名代碼的書寫格式的,而方法引用是用來進一步簡化Lambda表達式的,它簡化的更加過分。
3.1 靜態方法引用
類名::靜態方法
使用場景:如果某個Lambda表達式里只是調用一個靜態方法,并且前后參數的形式一致,就可以使用靜態方法引用。
public class Test1 {public static void main(String[] args) {Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊寶", 167.5, 24);// 原始寫法:對數組中的學生對象,按照年齡升序排序Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge(); // 按照年齡升序排序}});// 使用Lambda簡化后的形式Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());}
}
現在,我想要把這個Lambda表達式的方法體,用一個靜態方法代替
準備另外一個類CompareByData類,用于封裝Lambda表達式的方法體代碼;
public class CompareByData {public static int compareByAge(Student o1, Student o2){return o1.getAge() - o2.getAge(); // 升序排序的規則}
}
現在我們就可以把Lambda表達式的方法體代碼,改為下面的樣子
Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2));
Java為了簡化上面Lambda表達式的寫法,利用方法引用可以改進為下面的樣子。**實際上就是用類名調用方法,但是把參數給省略了。**這就是靜態方法引用
//靜態方法引用:類名::方法名
Arrays.sort(students, CompareByData::compareByAge);
3.2 實例方法引用
對象名::實例方法
使用場景:如果某個Lambda表達式里只是調用一個實例方法,并且前后參數的形式一致,就可以使用實例方法引用
現在,我想要把剛才的Lambda表達式Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
的方法體,用一個實例方法代替。
在CompareByData類中,再添加一個實例方法,用于封裝Lambda表達式的方法體
接下來,我們把Lambda表達式的方法體,改用對象調用方法
CompareByData compare = new CompareByData();
Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序
最后,再將Lambda表達式的方法體,直接改成方法引用寫法。實際上就是用對象名調用方法,但是省略的參數。這就是實例方法引用
CompareByData compare = new CompareByData();
Arrays.sort(students, compare::compareByAgeDesc); // 降序
3.2 特定類型的方法引用
類型::方法
使用場景:如果某個Lambda表達式里只是調用一個實例方法,并且前面參數列表中的第一個參數是作為方法的主調,
后面的所有參數都是作為該實例方法的入參的,則此時就可以使用特定類型的方法引用。
這種特定類型的方法引用是沒有什么道理的,只是語法的一種約定,遇到這種場景,就可以這樣用。
public class Test2 {public static void main(String[] args) {String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"};// 要求忽略首字符大小寫進行排序。Arrays.sort(names, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {// 制定比較規則。o1 = "Andy" o2 = "angela"return o1.compareToIgnoreCase(o2);}});//lambda表達式寫法Arrays.sort(names, ( o1, o2) -> o1.compareToIgnoreCase(o2) );//特定類型的方法引用!Arrays.sort(names, String::compareToIgnoreCase);System.out.println(Arrays.toString(names));}
}
3.3 構造器引用
類名::new
使用場景:如果某個Lambda表達式里只是在創建對象,并且前后參數情況一致,就可以使用構造器引用。
學習最后一種方法引用的形式,叫做構造器引用。還是先說明一下,構造器引用在實際開發中應用的并不多,目前還沒有找到構造器的應用場景。所以大家在學習的時候,也只是關注語法就可以了。
現在,我們準備一個JavaBean類,Car類
因為方法引用是基于Lamdba表達式簡化的,所以也要按照Lamdba表達式的使用前提來用,需要一個函數式接口,接口中代碼的返回值類型是Car類型
interface CreateCar{Car create(String name, double price);
}
最后,再準備一個測試類,在測試類中創建CreateCar接口的實現類對象,先用匿名內部類創建、再用Lambda表達式創建,最后改用方法引用創建。同學們只關注格式就可以,不要去想為什么(語法就是這么設計的)。
public class Test3 {public static void main(String[] args) {// 1、創建這個接口的匿名內部類對象。CreateCar cc1 = new CreateCar(){@Overridepublic Car create(String name, double price) {return new Car(name, price);}};//2、使用匿名內部類改進CreateCar cc2 = (name, price) -> new Car(name, price);//3、使用方法引用改進:構造器引用CreateCar cc3 = Car::new;//注意:以上是創建CreateCar接口實現類對象的幾種形式而已,語法一步一步簡化。//4、對象調用方法Car car = cc3.create("奔馳", 49.9);System.out.println(car);}
}
四、常見算法(跳過)
五、正則表達式
正則表達式其實是由一些特殊的符號組成的,它代表的是某種規則。
- 正則表達式的作用1:用來校驗字符串數據是否合法
- 正則表達式的作用2:可以從一段文本中查找滿足要求的內容
5.2 正則表達式書寫規則
這里需要用到一個方法叫matches(String regex)
(判斷字符串是否匹配正則表達式,匹配返回true,不匹配返回false。)。這個方法時屬于String類的方法。
這個方法是用來匹配一個字符串是否匹配正則表達式的規則,參數需要調用者傳遞一個正則表達式。但是正則表達式不能亂寫,是有特定的規則的。
public class RegexTest2 {public static void main(String[] args) {// 1、字符類(只能匹配單個字符)System.out.println("a".matches("[abc]")); // [abc]只能匹配a、b、cSystem.out.println("e".matches("[abcd]")); // falseSystem.out.println("d".matches("[^abc]")); // [^abc] 不能是abcSystem.out.println("a".matches("[^abc]")); // falseSystem.out.println("b".matches("[a-zA-Z]")); // [a-zA-Z] 只能是a-z A-Z的字符System.out.println("2".matches("[a-zA-Z]")); // falseSystem.out.println("k".matches("[a-z&&[^bc]]")); // : a到z,除了b和cSystem.out.println("b".matches("[a-z&&[^bc]]")); // falseSystem.out.println("ab".matches("[a-zA-Z0-9]")); // false 注意:以上帶 [內容] 的規則都只能用于匹配單個字符// 2、預定義字符(只能匹配單個字符) . \d \D \s \S \w \WSystem.out.println("徐".matches(".")); // .可以匹配任意字符System.out.println("徐徐".matches(".")); // false// \轉義System.out.println("\"");// \n \tSystem.out.println("3".matches("\\d")); // \d: 0-9System.out.println("a".matches("\\d")); //falseSystem.out.println(" ".matches("\\s")); // \s: 代表一個空白字符System.out.println("a".matches("\s")); // falseSystem.out.println("a".matches("\\S")); // \S: 代表一個非空白字符System.out.println(" ".matches("\\S")); // falseSystem.out.println("a".matches("\\w")); // \w: [a-zA-Z_0-9]System.out.println("_".matches("\\w")); // trueSystem.out.println("徐".matches("\\w")); // falseSystem.out.println("徐".matches("\\W")); // [^\w]不能是a-zA-Z_0-9System.out.println("a".matches("\\W")); // falseSystem.out.println("23232".matches("\\d")); // false 注意:以上預定義字符都只能匹配單個字符。// 3、數量詞: ? * + {n} {n, } {n, m}System.out.println("a".matches("\\w?")); // ? 代表0次或1次System.out.println("".matches("\\w?")); // trueSystem.out.println("abc".matches("\\w?")); // falseSystem.out.println("abc12".matches("\\w*")); // * 代表0次或多次System.out.println("".matches("\\w*")); // trueSystem.out.println("abc12張".matches("\\w*")); // falseSystem.out.println("abc12".matches("\\w+")); // + 代表1次或多次System.out.println("".matches("\\w+")); // falseSystem.out.println("abc12張".matches("\\w+")); // falseSystem.out.println("a3c".matches("\\w{3}")); // {3} 代表要正好是n次System.out.println("abcd".matches("\\w{3}")); // falseSystem.out.println("abcd".matches("\\w{3,}")); // {3,} 代表是>=3次System.out.println("ab".matches("\\w{3,}")); // falseSystem.out.println("abcde徐".matches("\\w{3,}")); // falseSystem.out.println("abc232d".matches("\\w{3,9}")); // {3, 9} 代表是 大于等于3次,小于等于9次// 4、其他幾個常用的符號:(?i)忽略大小寫 、 或:| 、 分組:()System.out.println("abc".matches("(?i)abc")); // trueSystem.out.println("ABC".matches("(?i)abc")); // trueSystem.out.println("aBc".matches("a((?i)b)c")); // trueSystem.out.println("ABc".matches("a((?i)b)c")); // false// 需求1:要求要么是3個小寫字母,要么是3個數字。System.out.println("abc".matches("[a-z]{3}|\\d{3}")); // trueSystem.out.println("ABC".matches("[a-z]{3}|\\d{3}")); // falseSystem.out.println("123".matches("[a-z]{3}|\\d{3}")); // trueSystem.out.println("A12".matches("[a-z]{3}|\\d{3}")); // false// 需求2:必須是”我愛“開頭,中間可以是至少一個”編程“,最后至少是1個”666“System.out.println("我愛編程編程666666".matches("我愛(編程)+(666)+"));System.out.println("我愛編程編程66666".matches("我愛(編程)+(666)+"));}
}
5.3 正則表達式應用案例
public class RegexTest3 {public static void main(String[] args) {checkPhone();}public static void checkPhone(){while (true) {System.out.println("請您輸入您的電話號碼(手機|座機): ");Scanner sc = new Scanner(System.in);String phone = sc.nextLine();// 18676769999 010-3424242424 0104644535if(phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")){System.out.println("您輸入的號碼格式正確~~~");break;}else {System.out.println("您輸入的號碼格式不正確~~~");}}}
}
5.4 正則表達式信息爬取
接下來我們學習正則表達式的第二個作用:在一段文本中查找滿足要求的內容
public class RegexTest4 {public static void main(String[] args) {method1();}// 需求1:從以下內容中爬取出,手機,郵箱,座機、400電話等信息。public static void method1(){String data = " 來黑馬程序員學習Java,\n" +" 電話:1866668888,18699997777\n" +" 或者聯系郵箱:boniu@itcast.cn,\n" +" 座機電話:01036517895,010-98951256\n" +" 郵箱:bozai@itcast.cn,\n" +" 郵箱:dlei0009@163.com,\n" +" 熱線電話:400-618-9090 ,400-618-4000,4006184000,4006189090";// 1、定義爬取規則String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2})"+ "|(400-?\\d{3,7}-?\\d{3,7})";// 2、把正則表達式封裝成一個Pattern對象Pattern pattern = Pattern.compile(regex);// 3、通過pattern對象去獲取查找內容的匹配器對象。Matcher matcher = pattern.matcher(data);// 4、定義一個循環開始爬取信息while (matcher.find()){String rs = matcher.group(); // 獲取到了找到的內容了。System.out.println(rs);}}
}
5.5 正則表達式搜索、替換
接下來,我們學習一下正則表達式的另外兩個功能,替換、分割的功能。需要注意的是這幾個功能需要用到Stirng類中的方法。這兩個方法其實我們之前學過,只是當時沒有學正則表達式而已。
public class RegexTest5 {public static void main(String[] args) {// 1、public String replaceAll(String regex , String newStr):按照正則表達式匹配的內容進行替換// 需求1:請把下面字符串中的不是漢字的部分替換為 “-”String s1 = "古力娜扎ai8888迪麗熱巴999aa5566馬爾扎哈fbbfsfs42425卡爾扎巴";System.out.println(s1.replaceAll("\\w+", "-"));// 需求2(拓展):某語音系統,收到一個口吃的人說的“我我我喜歡編編編編編編編編編編編編程程程!”,需要優化成“我喜歡編程!”。String s2 = "我我我喜歡編編編編編編編編編編編編程程程";System.out.println(s2.replaceAll("(.)\\1+", "$1"));// 2、public String[] split(String regex):按照正則表達式匹配的內容進行分割字符串,反回一個字符串數組。// 需求1:請把下面字符串中的人名取出來,使用切割來做String s3 = "古力娜扎ai8888迪麗熱巴999aa5566馬爾扎哈fbbfsfs42425卡爾扎巴";String[] names = s3.split("\\w+");System.out.println(Arrays.toString(names));}
}