1. 字符串相关的类
1.1 String 类
- String 声明为 final 的,不可被继承
- String 实现了 Serializable 接口:表示字符串是支持序列化的
- String 实现了 Comparable 接口:表示字符串是可以比较大小的
- String 在内部定义了 final char[] value 用于存储字符串数据
- 通过字面量的方式(
String s1 = "hhh"
)给一个字符串赋值,此时的字符串值声明在字符串常量池中,而字符串常量池中是不会存储相同内容的字符串的 - String 代表一个不可变的字符序列。
String 对象的创建
@Test
public void test() throws Exception {
String s1 = "大河之剑天上来!";// 大河之剑天上来!
String s2 = new String("大河之剑天上来!");// 大河之剑天上来!
char[] chs = {'大', '河', '之', '剑', '天', '上', '来', '!'};
String s3 = new String(chs);// 大河之剑天上来!
String s4 = new String(chs, 0, 4);// 大河之剑
}
其中:s1(字面量方式) 与 s2(构造器方式) 的区别如图:
在字符串的拼接操作中,只要涉及到了变量,就相当于 new 的方式:
String s1 = "aa" + "bb";
,此时 s1 代表的地址值直接指向常量池。String s2 = s1 + "cc";
,此时 s2 代表的地址值指向堆中。String s3 = s2.intern();
,此时 s3 代表的地址值会被强制的指向常量池。
常用方法
-
int length()
:返回字符串的长度 -
char charAt(int index)
:返回 index 处的字符 -
boolean isEmpty()
:判断字符串长度是否为0 -
String toUpperCase()
:将字符串每个字符都变成大写 -
String toLowerCase()
:将字符串每个字符都变成小写 -
String trim()
:忽略字符串前导空格和尾部空格 -
boolean equals(Object anObject)
:比较两个字符串内容是否相同 -
boolean equalsIgnoreCase(String anotherString)
:忽略大小写,比较两个字符串内容是否相同 -
String concat(String str)
:将 str 拼接到后面,相当于 + -
int compareTo(String anotherString)
:比较每一个字符,如果不相等,返回不相等字符的ASCII码差值;返回负数,代表当前对象小 -
String substring(int beginIndex)
:取子串,从 beginIndex 取到最后 -
String substring(int beginIndex, int endIndex)
:取子串,从 beginIndex 取到 endIndex,不包括 endIndex -
boolean startsWith(String prefix)
:是否以 prefix 开始 -
boolean startsWith(String prefix, int toffset)
:是否在指定 toffset 后以 prefix 开始 -
boolean endsWith(String suffix)
:是否以 suffix 开始 -
boolean contains(CharSequence s)
:是否包含字符序列 s (CharSequence 是一个接口,String 实现了该接口) -
int indexOf(String str)
:返回 str 第一次出现的索引,找不到就返回 -1 -
int indexOf(String str, int fromIndex)
:返回从 fromIndex 开始,str 第一次出现的索引,找不到就返回 -1 -
int lastIndexOf(String str)
:返回 str 最后一次出现的索引,找不到就返回 -1 -
int lastIndexOf(String str, int fromIndex)
:返回从 fromIndex 开始进行反向搜索,str 最后一次出现的索引,找不到就返回 -1indexOf() 与 lastIndexOf() 返回值相同,表明:① 字符串都不存在 或 ② 字符串只出现一次
-
String replace(char oldChar, char newChar)
:返回新的字符串,使用 newChar 替换原字符串中出现的所有的 oldChar -
replace(CharSequence target, CharSequence replacement)
:返回新的字符串,使用 replacement 替换原字符串中所有的 target 字符串 -
String replaceAll(String regex, String replacement)
:使用 replacement 替换此字符串匹配给定的正则表达式的子字符串 -
String replaceFirst(String regex, String replacement)
:使用 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串 -
boolean matches(String regex)
:是否匹配给定的正则表达式 -
String[] split(String regex)
:根据给定的正则表达式的匹配拆分此字符串 -
String[] split(String regex, int limit)
:根据匹配给定的正则表达式来拆分此字符串,最多不超过 limit 个,如果超过了,剩下的全部都放到最后一个元素中
String 与 char[] 之间的转换
@Test
public void test() throws Exception {
String s1 = "Dance";
char[] chars = s1.toCharArray();
String s2 = new String(chars);
}
String 与 byte[] 之间的转换
@Test
public void test() throws Exception {
String s1 = "Dance跳舞";
// 输出:[68, 97, 110, 99, 101, -24, -73, -77, -24, -120, -98]
// 使用默认的utf-8字符集,每个汉字占三位
byte[] bytes = s1.getBytes();
String s2 = new String(bytes);
/* 编码与解码要使用同一种字符集,否则会出现乱码的情况 */
// 输出:[68, 97, 110, 99, 101, -52, -8, -50, -24]
// 此时使用指定的字符集进行编码
byte[] gbkBytes = s1.getBytes("GBK");
String s3 = new String(gbkBytes, "GBK");
}
1.2 StringBuffer 类与 StringBuilder 类
- 底层都是用 char[] 存储
- StringBuffer:可变的字符序列;线程安全,效率偏低
- StringBuilder:可变的字符序列;线程不安全,效率高些
- 效率从高到低排序:StringBuilder > StringBuffer > String
源码分析
@Test
public void test() throws Exception {
String s1 = new String();// new char[0]
String s2 = new String("abc");// new char[]{'a', 'b', 'c'}
StringBuffer sb1 = new StringBuffer();// new char[16]
StringBuffer sb2 = new StringBuffer("abc");// new char[16 + "abc".length()]
}
- length() 返回的是实际的字符个数,不是 char[] 的长度
- 当添加的字符个数大于 char[] 的长度时,需要对其进行扩容。默认情况下,扩容为原来容量的2倍加2,同时将原有数组中的元素复制到新的数组中。由于数组复制会影响效率,为了避免扩容,开发中建议使用 StringBuffer(int capacity) 来直接指定容量。
常用方法
StringBuffer append(Xxx m)
:字符串的拼接StringBuffer delete(int start, int end)
:将索引从 start 到 end 的字符删除(左闭右开)StringBuffer replace(int start, int end, String str)
:将索引从 start 到 end 的字符使用 str 进行替换(左闭右开)StringBuffer insert(int offset, Xxx m)
:在索引 offset 处插入新的内容StringBuffer reverse()
:反转字符串void setCharAt(int index, char ch)
:替换指定索引的字符
2. JDK8之前的日期时间API
2.1 java.lang.System 类
static long currentTimeMillis()
:返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差(称为时间戳),适用于计算时间差
2.2 java.util.Date 类
两个构造器
Date date = new Date();
:创建当前时间的 Date 对象Date date = new Date(152693247814544L);
:创建指定毫秒数对应时间的 Date 对象
两个方法:
String toString()
:字符串格式为EEE MMM dd HH:mm:ss zzz yyyy
,比如 Thu Feb 25 08:19:07 CST 2021long getTime()
:返回 date 与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
2.3 java.sql.Date 类
- 构造器
Date date = new Date(124545687891L);
- 如何与 java.util.Date 转换:① 利用子父类的关系;② 利用毫秒数的关系(getTime() 可以获取毫秒数作为构造器的参数)
2.4 java.text.SimpleDateFormat 类
对日期 Date 类进行格式化和解析
- 使用默认的构造器
@Test public void test() throws Exception { SimpleDateFormat dateFormat = new SimpleDateFormat(); // 格式化 Date date1 = new Date();// Fri Feb 26 14:12:18 CST 2021 String str1 = dateFormat.format(date1);// 21-2-26 下午2:12 // 解析 String str2 = "21-5-21 下午1:15";// 默认只能解析该种格式的字符串 Date date2 = dateFormat.parse(str2);// Fri May 21 13:15:00 CST 2021 }
- 使用指定格式的构造器
@Test public void test() throws Exception { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 格式化 Date date1 = new Date();// Fri Feb 26 14:23:10 CST 2021 String str1 = dateFormat.format(date1);// 2021-02-26 14:23:10 // 解析 String str2 = "2020-02-26 14:07:10";// 只能解析指定格式的字符串 Date date2 = dateFormat.parse(str2);// Wed Feb 26 14:07:10 CST 2020 }
格式字符串可根据要求编写,详细参考 https://www.cnblogs.com/sunyanyan/p/5196198.html
2.5 java.util.Calendar 类
实例化
Calendar calendar1 = new GregorianCalendar();
// 返回的是一个 GregorianCalendar 对象
Calendar calendar2 = Calendar.getInstance();
常用方法
int get(int field)
:获取常用的属性信息Calendar calendar = Calendar.getInstance(); System.out.println(calendar.get(Calendar.DAY_OF_MONTH));// 获取当天是本月的第几天 System.out.println(calendar.get(Calendar.DAY_OF_YEAR));// 获取当天是本年的第几天
void set(int field, int value)
:设置常用的属性信息Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.DAY_OF_MONTH, 16); System.out.println(calendar.get(Calendar.DAY_OF_MONTH));// 16
void add(int field, int amount);
:在属性当前值的基础上相加Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, 1); System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
Date getTime()
:将 Calendar 对应的时间转换为 DateCalendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); System.out.println(date);// Fri Feb 26 16:19:29 CST 2021
void setTime(Date date)
:将 Date 对应的时间转换为 CalendarCalendar calendar = Calendar.getInstance(); Date date = new Date(); calendar.setTime(date); System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
注意
- 获取月份时,一月是0,二月是1……以此类推,十二月是11
- 获取星期时,周日是1,周一是2……以此类推,周六是7
3. JDK8中新的日期时间API
3.1 LocalDate、LocalTime、LocalDateTime 类
实例化
@Test
public void test() {
// 获取当前日期
LocalDate date = LocalDate.now();
System.out.println(date);// 2021-02-27
// 获取当前时间
LocalTime time = LocalTime.now();
System.out.println(time);// 15:41:34.901494300
// 获取当前日期时间
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime);// 2021-02-27T15:43:13.283611500
// 获取指定的日期时间
LocalDateTime dateTime1 = LocalDateTime.of(2020, 5, 20, 23, 11, 20);
System.out.println(dateTime1);// 2020-05-20T23:11:20
}
getXxx():获取相关的属性
@Test
public void test() {
LocalDateTime dateTime = LocalDateTime.now();
// 获取当前日期是本月的第几天 --> 27
System.out.println(dateTime.getDayOfMonth());
// 获取当前日期是本周的第几天 --> SATURDAY
System.out.println(dateTime.getDayOfWeek());
// 获取当前日期是本年的第几个月 --> FEBRUARY
System.out.println(dateTime.getMonth());
// 获取当前日期是本年的第几个月(对应的值) --> 2
System.out.println(dateTime.getMonthValue());
// 获取当前时间的分钟值 --> 11
System.out.println(dateTime.getMinute());
}
withXxx():设置相关的属性
@Test
public void test() {
LocalDateTime dateTime = LocalDateTime.now();
// 修改日期时间的天数,有返回值,不影响之前的数据
LocalDateTime dateTime1 = dateTime.withDayOfMonth(20);
System.out.println(dateTime);// 2021-02-27T19:20:18.648215100
System.out.println(dateTime1);// 2021-02-20T19:20:18.648215100
// 修改日期时间的小时数,有返回值,不影响之前的数据
LocalDateTime dateTime2 = dateTime.withHour(23);
System.out.println(dateTime);// 2021-02-27T19:22:05.784074
System.out.println(dateTime2);// 2021-02-27T23:22:05.784074
}
对属性进行加减操作
@Test
public void test() {
LocalDateTime dateTime = LocalDateTime.now();
// 增加日期时间的月份数,有返回值,不影响之前的数据
LocalDateTime dateTime1 = dateTime.plusMonths(3);
System.out.println(dateTime);// 2021-02-27T19:26:03.092869
System.out.println(dateTime1);// 2021-05-27T19:26:03.092869
// 减少日期时间的天数,有返回值,不影响之前的数据
LocalDateTime dateTime2 = dateTime.minusDays(7);
System.out.println(dateTime);// 2021-02-27T19:27:43.683547900
System.out.println(dateTime2);// 2021-02-20T19:27:43.683547900
}
3.2 Instant 类
时间线上的一个瞬时点,可能被用来记录应用程序中的事件时间戳
@Test
public void test() {
// 获取本初子午线的标准时间 --> 2021-02-27T11:58:39.514646100Z
Instant instant = Instant.now();
System.out.println(instant);
// 添加时区偏移量 --> 2021-02-27T19:58:39.514646100+08:00
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
// 获取瞬时点到1970年1月1日0时0分0秒(UTC时间)的毫秒数 --> 1614427331346
long millis = instant.toEpochMilli();
System.out.println(millis);
// 指定毫秒数来获取本初子午线的标准时间 --> 2009-02-28T01:25:58.763Z
Instant instant1 = Instant.ofEpochMilli(1235784358763L);
System.out.println(instant1);
}
3.3 DateTimeFormatter 类
格式化或解析日期时间
- 预定义的标准格式
@Test public void test() { DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 格式化 LocalDateTime localDateTime = LocalDateTime.now(); String formatStr = formatter.format(localDateTime); System.out.println(localDateTime);// 2021-02-28T12:21:34.639170 System.out.println(formatStr);// 2021-02-28T12:21:34.63917 // 解析,TemporalAccessor是父接口(多态形式) TemporalAccessor accessor = formatter.parse(formatStr); System.out.println(accessor);// {},ISO resolved to 2021-02-28T12:21:34.639170 }
- 本地化相关的格式
@Test public void test() { DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); DateTimeFormatter formatter3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withZone(ZoneId.systemDefault()); // 格式化 LocalDateTime localDateTime = LocalDateTime.now(); String formatStr1 = formatter1.format(localDateTime); String formatStr2 = formatter2.format(localDateTime); String formatStr3 = formatter3.format(localDateTime); System.out.println(localDateTime);// 2021-02-28T12:46:20.363752500 System.out.println(formatStr1);// 2021/2/28 下午12:46 System.out.println(formatStr2);// 2021年2月28日 下午12:46:20 System.out.println(formatStr3);// 2021年2月28日 CST 下午12:46:20 // 解析,TemporalAccessor是父接口(多态形式) TemporalAccessor accessor = formatter1.parse(formatStr1); System.out.println(accessor);// {},ISO resolved to 2021-02-28T12:46 }
@Test public void test() { DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); // 格式化 LocalDate localDate = LocalDate.now(); String formatStr = formatter.format(localDate); System.out.println(localDate);// 2021-02-28 System.out.println(formatStr);// 2021年2月28日星期日 // 解析,TemporalAccessor是父接口(多态形式) TemporalAccessor accessor = formatter.parse(formatStr); System.out.println(accessor);// {},ISO resolved to 2021-02-28 }
- 自定义的格式
@Test public void test() { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 格式化 LocalDateTime localDateTime = LocalDateTime.now(); String formatStr = formatter.format(localDateTime); System.out.println(localDateTime);// 2021-02-28T13:00:33.700695300 System.out.println(formatStr);// 2021-02-28 13:00:33 // 解析,TemporalAccessor是父接口(多态形式) TemporalAccessor accessor = formatter.parse(formatStr); System.out.println(accessor);// {},ISO resolved to 2021-02-28T13:00:33 }
3.4 其他类
ZoneId 类:包含了所有的时区信息
@Test
public void test() throws Exception {
// 获取所有的ZoneID
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
for (String zoneId : zoneIds) {
System.out.println(zoneId);// 形如 Europe/Belfast 的字符串
}
// 获取指定时区的时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(localDateTime);// 东京时间:2021-03-01T10:00:30.144(快一小时)
}
ZonedDateTime 类:带时区的日期时间
@Test
public void test() throws Exception {
// 获取本时区的ZonedDateTime对象
ZonedDateTime dateTime1 = ZonedDateTime.now();
System.out.println(dateTime1);// 2021-03-01T09:05:31.907+08:00[Asia/Shanghai]
// 获取指定时区的ZonedDateTime对象
ZonedDateTime dateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(dateTime2);// 2021-03-01T10:05:31.907+09:00[Asia/Tokyo]
}
Duration 类:用于计算两个“时间”间隔,以秒和纳秒为基准
@Test
public void test() throws Exception {
LocalTime localTime1 = LocalTime.now();
LocalTime localTime2 = LocalTime.of(15, 23, 32);
// 返回两个时间的间隔信息
Duration duration1 = Duration.between(localTime2, localTime1);
System.out.println(duration1);// PT-6H-12M-26.123S
System.out.println(duration1.getSeconds());// -22347
System.out.println(duration1.getNano());// 877000000
LocalDateTime localDateTime1 = LocalDateTime.now();
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 3, 1, 9, 10, 0);
Duration duration2 = Duration.between(localDateTime2, localDateTime1);
System.out.println(duration2.toDays());// 365
}
Period 类:用于计算两个“日期”间隔,以年、月、日衡量
@Test
public void test() throws Exception {
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2028, 3, 1);
Period period = Period.between(localDate2, localDate1);
System.out.println(period);// P-7Y
System.out.println(period.getYears());// -7
System.out.println(period.getMonths());// 0
System.out.println(period.getDays());// 0
Period period1 = period.withYears(2);
System.out.println(period1);// P2Y
}
TemporalAdjuster 类:时间校正器
@Test
public void test() throws Exception {
// 获取当前日期的下一个周日是哪天
TemporalAdjuster adjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
LocalDateTime localDateTime = LocalDateTime.now().with(adjuster);
System.out.println(localDateTime);// 2021-03-07T09:25:21.456
// 获取下一个工作日是哪天
LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = (LocalDate) temporal;
if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
return date.plusDays(3);
} else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
return date.plusDays(2);
} else {
return date.plusDays(1);
}
}
});
System.out.println(localDate);// 2021-03-02
}
新旧API之间的转换
4. Java比较器
4.1 Comparable 接口的使用(自然排序)
- 像 String、包装类等实现了 Comparable 接口,重写了
compareTo(obj)
,给出了比较两个对象大小的方式 - 像 String、包装类等重写了
compareTo(obj)
以后,进行了从小到大的排列 - 重写
compareTo(obj)
的规则:如果当前对象 this 大于形参对象 obj,则返回正整数;如果当前对象 this 小于形参对象 obj,则返回负整数;如果当前对象 this 等于形参对象 obj,则返回0 - 自定义类如果需要排序,可以让其实现 Comparable 接口,重写
compareTo(obj)
来指明如何排序
public class Good implements Comparable {
private String name;
private double price;
// 省略构造器与 get set 和 toString 方法
@Override
public int compareTo(Object o) {
if (o instanceof Good) {
Good good = (Good) o;
return Double.compare(this.getPrice(), good.getPrice());
}
throw new RuntimeException("传入的数据类型不一致");
}
}
4.2 Comparator 接口的使用(定制排序)
- 当元素的类型没有实现 Comparable 接口而又不方便修改代码,或者实现了 Comparable 接口的排序规则不适合当前的操作,此时可以考虑使用 Comparator 的对象来排序
- 重写
compare(Object o1, Object o2)
的规则:o1 大于 o2,方法返回正整数;o1 小于 o2,方法返回负整数;o1 等于 o2,方法返回0;
@Test
public void test() throws Exception {
Good[] goods = new Good[4];
Arrays.sort(goods, new Comparator<Good>() {
@Override
public int compare(Good o1, Good o2) {
return Integer.compare(o1.getName().length(), o2.getName().length());
}
});
System.out.println(Arrays.toString(goods));
}
5. System 类
- System 类代表系统,系统级的很多属性和控制方法都放置在该类的内部
- 构造器是 private 的,所以无法创建该类的对象;其内部的成员变量和成员方法都是 static 的,可以直接使用类来调用
成员变量:
- in:标准输入流(键盘输入)
- out:标准输出流(显示器)
- err:标准错误输出流(显示器)
成员方法:
long currentTimeMillis()
:返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差void exit(int status)
:退出程序,status 的值为0代表正常退出,非0代表异常退出void gc()
:请求系统进行垃圾回收,至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况String getProperty(String key)
:获得系统中属性名为 key 的属性对应的值。系统中常见的属性名以及属性的作用如下表:
属性名 | 属性说明 |
---|---|
java.version | Java运行时环境版本 |
java.home | Java安装目录 |
os.name | 操作系统的名称 |
os.version | 操作系统的版本 |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
6. Math 类
常用方法(都是静态方法)
int abs(int a)
:求 a 的绝对值(long,float,double)double sin(double a)
,double cos(double a)
,double tan(double a)
,double asin(double a)
,double acos(double a)
,double atan(double a)
:三角函数求值double sqrt(double a)
:求 a \sqrt {a} a 的值double pow(double a, double b)
:求 a 的 b 次幂的值double log(double a)
:求 l o g e a log_ea logea 的值double exp(double a)
:求 e a e^a ea 的值int max(int a, int b)
:求 a 和 b 之间的最大值(long,float,double)int min(int a, int b)
:求 a 和 b 之间的最小值(long,float,double)double random()
:随机获取一个[0.0, 1.0)之间的值,(Math.random() * (b - a + 1) + a)
用来获取 [a,b] 的整数int round(float a)
:四舍五入(double 类型的参数转换为 long 类型)double ceil(double a)
:向上取整double floor(double a)
:向下取整double toDegrees(double angrad)
:将弧度转换为角度double toRadians(double angdeg)
:将角度转换为弧度
7. BigInteger 类与 BigDecimal 类
- BigInteger 可以表示不可变的任意精度的整数,该类提供了加减乘除等方法
- BigDecimal 可以在数字精度要求较高时使用,该类提供了加减乘除等方法
@Test public void test() throws Exception { BigDecimal bd1 = new BigDecimal("12345.351"); BigDecimal bd2 = new BigDecimal("11"); // 如果不通过参数来指定处理方式,bd1.divide(bd2)会报错 System.out.println(bd1.divide(bd2, BigDecimal.ROUND_HALF_UP));// 1122.305 System.out.println(bd1.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));// 1122.304636363636364 }