【JavaSE五天速通|第三篇】常用API与日期类篇

适合有其他语言基础想快速入门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));}
}

IntToDoubleFunctionJava8新引入的函数式接口,它的作用是:

  • 接受一个 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));}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96915.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96915.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8s学习笔记(二) Pod入门与实战

1 K8s核心资源Pod 1.1 Pod是什么&#xff1f; 官方文档&#xff1a;Pod | Kubernetes Pod 是 Kubernetes&#xff08;k8s&#xff09;中最小的部署与调度单元&#xff0c;并非直接运行容器&#xff0c;而是对一个或多个 “紧密关联” 容器的封装。 核心特点可简单总结为 3 …

用 Python 调用 Bright Data MCP Server:在 VS Code 中实现实时网页数据抓取

用 Python 调用 Bright Data MCP Server&#xff1a;在 VS Code 中实现实时网页数据抓取&#xff0c;本文介绍了Bright Data的Web MCP Server&#xff0c;这是一款能实现实时、结构化网页数据访问的API&#xff0c;适用于AI应用等场景。其支持静态与动态网页&#xff0c;前3个月…

SPSS绘制ROC曲线并计算灵敏度、特异度

SPSS绘制ROC曲线并计算灵敏度、特异度。 &#xff08;1&#xff09;绘制ROC曲线&#xff1a; 输入&#xff1a;预测值、受试者标签。 在SPSS中点击“分析”-“分类”-“ROC曲线” 变量输入&#xff1a;检验变量输入预测值&#xff0c;状态变量输入受试者标签&#xff0c;如果标…

Modbus协议原理与Go语言实现详解

目录 Modbus协议概述协议架构与通信模式Modbus数据模型Modbus协议帧格式功能码详解Go Modbus库完整实现高级应用示例调试与故障排除 Modbus协议概述 Modbus是一种串行通信协议&#xff0c;由Modicon公司&#xff08;现施耐德电气&#xff09;于1979年开发&#xff0c;用于PL…

下载CentOS 7——从阿里云上下载不同版本的 CentOS 7

没有废话&#xff0c;直接上干货。跟着图片教程&#xff0c;一步一步来就行。 想下载其它版本的&#xff0c;自己可以再选择其它的就行。 想省事的朋友可以直接点击: 1、下载页面链接 2、CentOS-7-x86_64-DVD-2207-02(4.4GB).iso

SpringBoot -原理篇

文章目录配置优先级Bean管理获取beanbean作用域第三方beanSpringBoot原理起步依赖自动配置自动配置原理方案源码跟踪原理分析 Conditional案例&#xff08;自定义starter&#xff09;案例&#xff08;自定义starter分析&#xff09;案例&#xff08;自定义starter实现&#xff…

JavaScript与jQuery:从入门到面试的完整指南

JavaScript与jQuery&#xff1a;从入门到面试的完整指南 第一部分&#xff1a;JavaScript基础 1.1 JavaScript简介 JavaScript是一种轻量级的解释型编程语言&#xff0c;主要用于Web开发&#xff0c;可以为网页添加交互功能。它是ECMAScript规范的一种实现。 // 第一个JavaScri…

解决:Ubuntu、Kylin、Rocky系统中root用户忘记密码

解决Linux系统中root用户忘记密码 Ubuntu2204 重启电脑&#xff0c;启动时&#xff0c;长按Shift键&#xff08;对于 BIOS 系统&#xff09;或 Esc 键&#xff08;对于 UEFI 系统&#xff09;进入GRUB菜单 步骤1&#xff1a;重启Ubuntu系统&#xff0c;长按Shift键进入Ubuntu…

ENVI系列教程(二)——自定义坐标系(北京 54、西安 80、2000 坐标系)

目录 1 概述 1.1 地理投影的基本原理 1.2 国内坐标系介绍 1.3 参数的获取 2 详细操作步骤 2.1 添加椭球体 2.2 添加基准面 2.3 定义坐标系 2.4 使用自定义坐标系 1 概述 1.1 地理投影的基本原理 常用到的地图坐标系有 2 种,即地理坐标系和投影坐标系。地理坐标系是…

一种基于因果干预的少样本学习的故障诊断模型

一、研究背景与问题 ​工业背景​:机械故障诊断对工业系统安全至关重要,但实际中故障样本稀少,难以训练传统深度学习模型。 ​现有问题​: 当前少样本学习(FSL)方法大多基于相关性而非因果关系建模,容易学习到伪相关特征,导致模型可解释性差、泛化能力弱。 跨组件故障诊…

机器视觉光源的尺寸该如何选型的方法

机器视觉光源的尺寸该如何选型的方法&#x1f3af;机器视觉光源的尺寸选型的方法&#x1f3af;一、选型案例&#x1f3af;二、照射方式&#x1f3af;三、镜头选择&#x1f3af;四、光源架构光源的工作距离与视野大小&#x1f3af;五、总结&#xff1a;光源选型 —— 机器视觉检…

HTML新属性

HTML5引入了许多新属性&#xff0c;旨在增强语义化、交互性和多媒体支持。以下是一些重要的新属性及其用途分类&#xff1a;语义化与结构属性data-*&#xff1a;自定义数据属性&#xff0c;允许开发者存储额外信息&#xff08;如data-id"123"&#xff09;。hidden&am…

从工地到链上:一个土建人的 Web3 转行经历

Web3 的风&#xff0c;终究还是吹到了土建行业。2017 年&#xff0c;土建专业&#xff08;给排水工程&#xff09;的刘正源偶然看到一则关于比特币的新闻&#xff0c;被它背后的经济模型与技术架构深深震撼。到了 2021 年&#xff0c;他在工地上再次听人提起区块链&#xff0c;…

20250914-03: Langchain概念:提示模板+少样本提示

20250914-03: Langchain概念&#xff1a;提示模板少样本提示 聊天模型 消息 提示 结构化输出 &#x1f3af; 学习目标 掌握如何“喂给模型正确的输入”并“解析出想要的输出”。 &#x1f517; 核心概念 ​聊天模型&#xff08;ChatModel&#xff09;​消息&#xff08;M…

【AI推理部署】Docker篇04—Docker自动构建镜像

Docker 自动构建镜像1. Dockfile 编写2. 镜像使用使用 Dockerfile 构建镜像 Dockerfile 其实就是把我们前面的一系列安装、配置命令写到一个文件中&#xff0c;通过 docker build 命令&#xff0c;一键完成镜像的构建。接下来&#xff0c;我们以 bitnami/pytorch:2.1.1 作为基础…

LeetCode 674.最长连续递增序列

给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r&#xff08;l < r&#xff09;确定&#xff0c;如果对于每个 l < i < r&#xff0c;都有 nums[i] < nums[i 1] &am…

贪心算法java

贪心算法简介贪心算法是一种在每一步选择中都采取在当前状态下最优&#xff08;局部最优&#xff09;的选择&#xff0c;从而希望导致结果是全局最优的算法。贪心算法通常用于解决最优化问题&#xff0c;如最短路径、最小生成树、任务调度等。贪心算法的基本步骤问题分析&#…

【华为OD】解锁犯罪时间

【华为OD】解锁犯罪时间 题目描述 警察在侦破一个案件时&#xff0c;得到了线人给出的可能犯罪时间&#xff0c;形如"HH:MM"表示的时刻。根据警察和线人的约定&#xff0c;为了隐蔽&#xff0c;该时间是修改过的&#xff0c;解密规则为&#xff1a;利用当前出现过的数…

基于linux操作系统的mysql安装

一、检查自己的操作系统是否已经有存在的mysql 1.存在 2.不存在 二、基于操作系统不存在mysql,找官方yum源 网址&#xff1a; Index of /232905https://repo.mysql.com/ 网站打开是这样 看看自己的操作系统是哪个版本&#xff0c;再下载哪个版本&#xff0c;如果和我一样装…

如何用 Git Hook 和 CI 流水线为 FastAPI 项目保驾护航?

url: /posts/fc4ef84559e04693a620d0714cb30787/ title: 如何用Git Hook和CI流水线为FastAPI项目保驾护航? date: 2025-09-14T00:12:42+08:00 lastmod: 2025-09-14T00:12:42+08:00 author: cmdragon summary: 持续集成(CI)在FastAPI项目中通过频繁合并代码和自动验证,确保…