面向对象进阶4(常用日期API、正则、Arrays类、Lambda)
# 面向对象进阶4(常用日期API、正则、Arrays类、Lambda)
# 1. 日期与时间
这部分的内容了解即可,JDK8 新增的日期类比本部分中的好用
# 1.1 Date 类
Date 类代表当前所在系统的日期时间信息
构造器
名称 | 说明 |
---|---|
public Date() | 创建一个Date对象,代表的是系统当前此刻日期时间。 |
public Date(long time) | 把时间毫秒值转换成Date日期对象 |
常用方法
名称 | 说明 |
---|---|
public long getTime() | 返回从1970年1月1日 00:00:00走到此刻的总的毫秒数 |
public void setTime(long time) | 设置日期对象的时间为当前时间毫秒值对应的时间 |
日期对象如何创建,如何获取时间毫秒值?
public Date();
public long getTime();
时间毫秒值怎么恢复成日期对象?
public Date(long time);
public void setTime(long time);
# 1.2 SimpleDateFormat
作用:
完成日期时间的格式化操作
public SimpleDateFormat(String pattern):构造一个SimpleDateFormat,使用指定的格式
格式化方法 说明 public final String format(Date date) 将日期格式化成日期/时间字符串 public final String format(Object time) 将时间毫秒值式化成日期/时间字符串 解析字符串时间成为日期对象
2011-11-11 11:11:22 -> Date日期对象
public Date parse(String source):从给定字符串的开始解析文本以生成日期
# 1.3 Calendar
Calendar代表了系统此刻日期对应的日历对象
Calendar是一个抽象类,不能直接创建对象
Calendar日历类创建日历对象的方法:public static Calendar getInstance(),获取当前日历对象
Calendar常用方法
方法名 说明 public int get(int field) 取日期中的某个字段信息。 public void set(int field,int value) 修改日历的某个字段信息。 public void add(int field,int amount) 为某个字段增加/减少指定的值 public final Date getTime() 拿到此刻日期对象。 public long getTimeInMillis() 拿到此刻时间毫秒值
⚠️ **注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化
# 2. JDK8 新增日期类
从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:
LocalDate:不包含具体时间的日期。
LocalTime:不含日期的时间。
LocalDateTime:包含了日期及时间。
Instant:代表的是时间戳。
DateTimeFormatter 用于做时间的格式化和解析的
Duration:用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔
新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便
新API的类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改
# 2.1 LocalDate、LocalTime、LocalDateTime
分别表示日期、时间、日期时间对象,他们的类的实例是不可变的对象,他们三者构建对象和API都是通用的
构建对象的方式如下:
方法名 | 说明 | |
---|---|---|
public static Xxxx now(); | 静态方法,根据当前时间创建对象 | LocaDate localDate = LocalDate.now(); LocalTime llocalTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); |
public static Xxxx of(…); | 静态方法,指定日期/时间创建对象 | LocalDate localDate1 = LocalDate.of(2099 , 11,11); LocalTime localTime1 = LocalTime.of(11, 11, 11); LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43); |
LocalDate、LocalTime、LocalDateTime获取信息的API:
方法名 | 说明 |
---|---|
public int geYear() | 获取年 |
public int getMonthValue() | 获取月份(1-12) |
Public int getDayOfMonth() | 获取月中第几天乘法 |
Public int getDayOfYear() | 获取年中第几天 |
Public DayOfWeek getDayOfWeek() | 获取星期 |
提示
具体使用时查看 IDEA 提示的方法即可
转换相关 API:
LocalDateTime的转换API:
方法名 | 说明 |
---|---|
public LocalDate toLocalDate() | 转换成一个LocalDate对象 |
public LocalTime toLocalTime() | 转换成一个LocalTime对象 |
和时间修改相关的 API:
LocalDateTime 综合了 LocalDate 和 LocalTime 里面的方法,所以下面只用 LocalDate 和 LocalTime 来举例。这些方法返回的是一个新的实例引用,因为LocalDateTime 、LocalDate 、LocalTime 都是不可变的
方法名 | 说明 |
---|---|
plusDays, plusWeeks, plusMonths, plusYears | 向当前 LocalDate 对象添加几天、 几周、几个月、几年 |
minusDays, minusWeeks, minusMonths, minusYears | 从当前 LocalDate 对象减去几天、 几周、几个月、几年 |
withDayOfMonth, withDayOfYear, withMonth, withYear | 将月份天数、年份天数、月份、年 份 修 改 为 指 定 的 值 并 返 回 新 的 LocalDate 对象 |
isBefore, isAfter, equals | 比较两个 LocalDate |
# 2.2 Instant 时间戳
JDK8 获取时间戳特别简单,且功能更丰富。Instant 类由一个静态的工厂方法 now() 可以返回当前时间戳
Instant instant = Instant.now();
System.out.println("当前时间戳是:" + instant);
Date date = Date.from(instant);
System.out.println("当前时间戳是:" + date);
instant = date.toInstant();
System.out.println(instant);
2
3
4
5
6
7
8
💡 时间戳是包含日期和时间的,与 java.util.Date 很类似,事实上 Instant 就是类似 JDK8 以前的 Date。
💡 Instant和Date这两个类可以进行转换
# 2.3 DateTimeFormatter
在 JDK8 中,引入了一个全新的日期与时间格式器 DateTimeFormatter,正反都能调用format方法。
示例代码:
public class Demo06DateTimeFormat {
public static void main(String[] args) {
// 本地此刻 日期时间 对象
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// 解析/格式化器
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
// 正向格式化(对象调用可以瞎搞)
System.out.println(dtf.format(ldt));
// 逆向格式化
System.out.println(ldt.format(dtf));
// 解析字符串时间
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 解析当前字符串时间成为本地日期时间对象
LocalDateTime ldt1 = LocalDateTime.parse("2019-11-11 11:11:11" , dtf1);
System.out.println(ldt1);
System.out.println(ldt1.getDayOfYear());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
格式化的时间形式的常用的模式对应关系如下:
# 2.4 Duration/Period/ChronoUnit
JDK8 中,用来计算两个**“日期”间隔的类:java.time.Period;用来计算两个“时间”间隔**的类:java.time.Duration。
最全的工具类:java.time.temporal.ChronoUnit,可以用于比较所有的时间单位。
# 2.4.1 Period 类
主要是 Period 类方法 getYears(),getMonths() 和 getDays() 来计算,只能精确到年月日。
用于 LocalDate 之间的比较
示例代码:
public class Demo07Period {
public static void main(String[] args) {
// 当前本地 年月日
LocalDate today = LocalDate.now();
System.out.println(today);//
// 生日的 年月日
LocalDate birthDate = LocalDate.of(1998, 10, 13);
System.out.println(birthDate);
Period period = Period.between(birthDate, today);//第二个参数减第一个参数
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2.4.2 Duration 类
提供了使用基于时间的值测量时间量的方法
用于 LocalDateTime 之间的比较。也可用于 Instant 之间的比较
示例代码:
public class Demo08Duration {
public static void main(String[] args) {
// 本地日期时间对象。
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 出生的日期时间对象
LocalDateTime birthDate = LocalDateTime.of(2021,8,06,01,00,00);
System.out.println(birthDate);
Duration duration = Duration.between(today, birthDate);//第二个参数减第一个参数
System.out.println(duration.toDays());//两个时间差的天数
System.out.println(duration.toHours());//两个时间差的小时数
System.out.println(duration.toMinutes());//两个时间差的分钟数
System.out.println(duration.toMillis());//两个时间差的毫秒数
System.out.println(duration.toNanos());//两个时间差的纳秒数
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2.4.3 ChronoUnit 类
ChronoUnit 类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位。
示例代码:
public class Demo09ChronoUnit {
public static void main(String[] args) {
// 本地日期时间对象:此刻的
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 生日时间
LocalDateTime birthDate = LocalDateTime.of(1990,10,1,
10,50,59);
System.out.println(birthDate);
System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 3. 包装类
8种基本数据类型对应的引用类型
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
💡 提供包装类的原因:
- Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
- 集合和泛型只支持包装类型,不支持基本数据类型
包装类的特性:
自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量
**自动拆箱:**包装类型的变量可以直接赋值给基本数据类型的变量
包装类的特有功能:
✨ 包装类的变量的默认值可以是null,容错率更高
可以把基本类型的数据转换成字符串类型(用处不大)
因为可以直接+字符串得到字符串类型
如:
String rs2 = i3 + "";
①调用toString()方法得到字符串结果。
②调用Integer.toString(基本类型的数据)。
✨ 可以把字符串类型的数值转换成真实的数据类型(真的很有用)
①Integer.parseInt(“字符串类型的整数”)
②Double.parseDouble(“字符串类型的小数”)
③Integer/Double.valueOf(“字符串类型的数值”) --> 比前两个好使,直接使用统一的方法
代码示例:
String number = "23"; //转换成整数 // int age = Integer.parseInt(number); int age = Integer.valueOf(number); System.out.println(age + 1); // 24 String number1 = "99.9"; //转换成小数 //double score = Double.parseDouble(number1); double score = Double.valueOf(number1); System.out.println(score + 0.1); // 100.0
1
2
3
4
5
6
7
8
9
10
11
# 4. 正则表达式
正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法。如,校验用户名、密码、验证码等输入数据的合法性。
字符串对象提供了匹配正则表达式的方法:
public boolean matches([String regex)
: 判断是否匹配正则表达式,匹配返回true,不匹配返回false
匹配规则:
字符类(默认匹配一个字符)
正则表达式 匹配结果 [abc] 只能是a, b, 或c [^abc] 除了a, b, c之外的任何字符 [a-zA-Z] a到z A到Z,包括(范围) [a-d[m-p]]] a到d,或m通过p:([a-dm-p]联合) [a-z&&[def]] d, e, 或f(交集) [a-z&&[^bc]] a到z,除了b和c [a-z&&[^m-p]] a到z,除了m到p 预定义的字符类(默认匹配一个字符)
正则表达式 匹配结果 . 任何字符 \d 一个数字: [0-9] \D 非数字: [^0-9] \s 一个空白字符:[ \t\n\x0B\f\r] \S 非空白字符:[^\s] \w [a-zA-Z_0-9] 英文、数字、下划线 \W [^\w] 一个非单词字符 ⚠️ 此处的 “\...” 在写代码时要用“\\”。
贪婪的量词(配合匹配多个字符)
正则表达式 匹配结果 X? X , 一次或根本不 X* X,零次或多次 X+ X,一次或多次 X{n} X,正好n次 X{n,} X,至少n次 X{n,m} X,至少n但不超过m次
正则表达式在字符串方法中的使用:
方法名 | 说明 |
---|---|
public String replaceAll(String regex,String newStr) | 按照正则表达式匹配的内容进行替换 |
public String[] split(String regex): | 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 |
代码示例:
public class RegexDemo04 {
public static void main(String[] args) {
String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";
String[] arrs = names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
String names2 = names.replaceAll("\\w+", " ");
System.out.println(names2); // 小路 蓉儿 小何
}
}
2
3
4
5
6
7
8
9
10
11
12
13
使用正则表达式爬取信息中的内容:
示例代码:
public class RegexDemo05 {
public static void main(String[] args) {
String rs = "来黑马程序学习Java,电话020-43422424,或者联系邮箱" +
"itcast@itcast.cn,电话18762832633,0203232323" +
"邮箱bozai@itcast.cn,400-100-3233 ,4001003232";
// 需求:从上面的内容中爬取出 电话号码和邮箱。
// 1、定义爬取规则,字符串形式
String regex = "(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})";
// 2、把这个爬取规则编译成匹配对象。
Pattern pattern = Pattern.compile(regex);
// 3、得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
// 4、开始找了
while (matcher.find()) {
String rs1 = matcher.group();
System.out.println(rs1);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 5. Arrays 类
Arrays 类是数组操作工具类,专门用于操作数组元素的。
Arrays类的常用 API :
方法名 | 说明 |
---|---|
public static String toString(类型[] a) | 返回数组的内容(字符串形式) |
public static void sort(类型[] a) | 对数组进行默认升序排序 |
public static <T> void sort(类型[] a, Comparator<? super T> c) | 使用比较器对象自定义排序 |
public static int binarySearch(int[] a, int key) | 二分搜索数组中的数据,存在返回索引,不存在返回-1 |
代码示例:
int[] arr = {10, 2, 55, 23, 24, 100};
System.out.println(Arrays.toString(arr));
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
2
3
4
5
Arrays 类对于 Comparator 比较器的支持:
可以通过设置 Comparator 接口对应的比较器对象,来定制比较规则
如果认为左边数据 大于 右边数据 返回正整数
如果认为左边数据 小于 右边数据 返回负整数
如果认为左边数据 等于 右边数据 返回0
⚠️ 被排序的数组 必须是引用类型的元素
代码示例:
// 2、需求:降序排序!(自定义比较器对象,只能支持引用类型的排序!!)
Integer[] ages1 = {34, 12, 42, 23};
/**
参数一:被排序的数组 必须是引用类型的元素
参数二:匿名内部类对象,代表了一个比较器对象。
*/
Arrays.sort(ages1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 指定比较规则。
// if(o1 > o2){
// return 1;
// }else if(o1 < o2){
// return -1;
// }
// return 0;
// return o1 - o2; // 默认升序
return o2 - o1; // 降序
}
});
System.out.println(Arrays.toString(ages1));
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
上述比较规则可以简化为:
Arrays.sort(ages1, ( o1, o2 ) -> o2 - o1 );
# 6. Lambda 表达式
Lambda表达式是JDK 8开始后的一种新语法形式
**作用:**简化匿名内部类的代码写法
Lambda 表达式的简化格式:
(匿名内部类被重写方法的形参列表) -> {
被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
2
3
4
5
⚠️ 注意: Lambda 表达式只能简化函数式接口的匿名内部类的写法形式
函数式接口要求:
- 必须是接口
- 接口中有且仅有一个抽象方法
- 若有
@FunctionalInterface
注解,则表明该接口是一个函数式接口
示例简化常见函数式接口:
**Lambda 表达式的省略规则: **
- 参数类型可以省略不写。
- 如果只有一个参数,参数类型可以省略,同时()也可以省略。
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写