一、常用类
1.1 Date类
1.1.1 java.util.date
Date类用于获取当前日期,具体用法如下面代码所示:
Date date = new Date();
System.out.println(date);
System.out.println(date.toString());
// 获取格林尼治时间
System.out.println(date.toGMTString());
// 获取本地时间
System.out.println(date.toLocaleString());
// 注意:这里是获取从 1900年到现在 之间的年份数
System.out.println(date.getYear());
// 获取月份,注意,月份是从 0开始的
System.out.println(date.getMonth());
// 获取从1970.1.1 00:00:00到现在的毫秒数
System.out.println(date.getTime());
// 获取从1970.1.1 00:00:00到现在的毫秒数
System.out.println(System.currentTimeMillis());
/**
* 思考。date.getTime 和 System.currentTimeMillis()哪个更好?
* 答案:System.currentTimeMillis() 更好
* 原因:
* 1. date.getTime需要去new一个Date对象,但是 System.currentTimeMillis() 不需要
* 2. public static native long currentTimeMillis();
* 这个 native说明这是一个本地方法,是Java通过调用其他的方法生成的
* 3. 应用场景如下:记录一个算法的耗时
*/
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("这段算法的耗时是:" + (end - start));
1.1.2 java.sql.date
java.util.date 和 java.sql.date的区别:
java.util.date 返回的是年月日 时分秒
java.util.date 返回的是年月日
java.util.date 和 java.sql.date的联系:
java.sql.date extends java.util.date
java.util.date 和 java.sql.date的转换->代码如下:
// java.util.date -> java.sql.date
java.util.Date date1 = new java.util.Date();
java.sql.Date date2 = (java.sql.Date) date1;
// 这样代码会报错,Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Date
//原因就是 date1并没有 指定父类指向的是 sql.Date
// 正确的写法应该是
// java.util.date -> java.sql.date
java.util.Date date = new java.util.Date();
java.util.Date date1 = new java.sql.Date(date.getTime());
java.sql.Date date2 = (java.sql.Date) date1;
// java.sql.date -> java.util.date
java.util.Date date1 = new java.sql.Date(15678778789L);;
System.out.println(date1);
// 字符串转为sql.Date
java.sql.Date date = Date.valueOf("2023-5-3");
System.out.println(date);
1.1.3 SimpleDateFormate
/**
引入:String -> java.util.Date
思路:String -> java.sql.Date -> java.util.Date
*/
java.sql.Date date=Date.valueOf("2023-5-3");
java.util.Date date2 = date;
/**
这样是可以转成功的,但是 Date.valueOf的参数变成 2023/5/3 就会报错:
java.lang.IllegalArgumentException
为了解决这样的日期格式问题,java中引入了SimpleDateFormate
*/
// 基本用法
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
// String -> Date
Date parse = df.parse("2023-5-3 13:23:45");
System.out.println(parse);
} catch (ParseException e) {
e.printStackTrace();
}
// Date -> String
String format = df.format(new Date());
System.out.println(format);
// 前言 报出的异常:java.lang.IllegalArgumentException
// 用此方案就可以解决,这也是SimpleDateFormate解决问题的场景
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
try {
// String -> Date
Date parse = df.parse("2023/5/3");
System.out.println(parse);
} catch (ParseException e) {
e.printStackTrace();
}
1.1.4 Calendar
Date中的很多方法都是过时的,Calendar有这些功能,具体用法为
// 实例化Calendar对象
// 方式一
Calendar cal = Calendar.getInstance();
// 方式二
Calendar cal2 = new GregorianCalendar();
// get方法
System.out.println(cal.get(Calendar.YEAR));
// 月份从0开始计算
System.out.println(cal.get(Calendar.MONTH));
System.out.println(cal.get(Calendar.DATE));
System.out.println(cal.get(Calendar.DAY_OF_MONTH));
System.out.println(cal.get(Calendar.WEEK_OF_MONTH));
// 默认以星期天作为一周的开始
System.out.println(cal.get(Calendar.DAY_OF_WEEK));
// 设置以星期一为一周的开始
cal.setFirstDayOfWeek(Calendar.MONDAY);
System.out.println(cal.getActualMaximum(Calendar.DATE)); // 获取本月最大的天数
System.out.println(cal.getActualMinimum(Calendar.DATE)); // 获取本月最小的天数
// set方法
cal.set(Calendar.YEAR,2019);
cal.set(Calendar.MONTH,11);
cal.set(Calendar.DATE,23);
System.out.println(cal);
/**
* String -> Calendar
* 思路:
* 1. String -> java.sql.Date
* 2. java.sql.Date -> Calendar
*/
java.sql.Date date = java.sql.Date.valueOf("2020-04-12");
cal.setTime(date);
System.out.println(cal);
/**
* 案例:输入年月日,打印这个月的日历
*/
System.out.println("请输入类似 yyyy-MM-dd的日期:(打印本月日历)");
String inputWords = new Scanner(System.in).nextLine();
System.out.println("日\t一\t二\t三\t四\t五\t六");
// 1.字符串转date
Date date = Date.valueOf(inputWords);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// 获取一个月有多少天
int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
// 获取输入日期记录的天数
int inputDay = cal.get(Calendar.DATE);
// 设置日期从1号开始
cal.set(Calendar.DATE,1);
// 获取当月第一天是周几
int firstDayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
int count = 0; // 计数器
// 前面先打印空格
for (int i = 0; i < firstDayOfWeek - 1; i++) {
System.out.print("\t");
count += 1;
}
// 遍历这个月的天数
for (int i = 1; i <= maxDay; i++) {
if (i == inputDay){
System.out.print(i+"*\t");
}else {
System.out.print(i+"\t");
}
count += 1;
if (count % 7 == 0){
System.out.println();
}
}
1.1.5 jdk1.8之后新增的日期类
出现的原因
/**java
* jdk1.0使用java.util.Date作为日期类 -> 第一代日期api
* jdk1.1使用calendar作为日期类 -> 第二代日期api
* jdk1.8又提供了新的日期类api
* 为啥有了1.0和1.1的日期api,还出现了1.8的api:
* 1. 可变性:像日期和时间这样的类应该是不可变的
* 2. Date中的年份是从1900年开始,而月份是从0开始
* 3. 格式化只对Date有用,对Calendar没用
*/
1.1.5.1 localDate/localTime/localDateTime 实例化方法
// 实例化方式1
// now方法,获取当前日期
LocalDate localDate = LocalDate.now(); // 2023-05-04
LocalTime localTime = LocalTime.now(); // 23:28:35.990 时:分:秒:毫秒
LocalDateTime localDateTime = LocalDateTime.now(); // 2023-05-04T23:28:35.990
// 实例化方法2
// of方法,可以指定日期
LocalDate localDate1 = LocalDate.of(2020, 9, 16);
LocalTime localTime1 = LocalTime.of(17, 5, 34);
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 9, 15, 4, 3, 35);
1.1.5.2 get和with方法
// get方法
// LocalDate和LocalTime都没有LocalDateTime使用的频率高
// 之后就以LocalDateTime演示为例
// 可以看出LocalDateTime获取的时间没有偏移差
System.out.println(localDateTime.getYear()); // 2023
System.out.println(localDateTime.getMonth()); // MAY
System.out.println(localDateTime.getMonthValue()); // 5
System.out.println(localDateTime.getDayOfMonth()); // 4
System.out.println(localDateTime.getDayOfWeek()); // THURSDAY
System.out.println(localDateTime.getHour()); // 23
System.out.println(localDateTime.getMinute()); // 35
System.out.println(localDateTime.getSecond()); // 0
// with方法,由于localDateTime是不可变的,因此改变localDateTime的值,会生成一个新的对象
// 改变其他的日期值也是类似的
LocalDateTime newLocalDateTime = localDateTime.withYear(2022);
System.out.println(localDateTime); // 2023-05-04T23:39:27.624
System.out.println(newLocalDateTime); // 2022-05-04T23:39:27.624
1.1.5.3 localDateTime加减法
// 由于localDateTime是不可变的,因此对日期进行
// 加减法的时候,也会生成一个新的对象
// 日期的其他 月/日/时/分/秒的方法与下面的类比即可
LocalDateTime localDateTime = LocalDateTime.now(); // 2023-05-04T23:42:51.507
// 加法
LocalDateTime localDateTime1 = localDateTime.plusYears(2); // 2025-05-04T23:42:51.507
// 减法
LocalDateTime localDateTime2 = localDateTime.minusYears(1); // 2022-05-04T23:42:51.507
1.1.5.4 针对localDate/localTime/localDateTime格式化
1.1.5.4.1 预定义格式化
有三个预定义的值:
DateTimeFormatter.ISO_DATE --> 针对localDate的格式化
DateTimeFormatter.ISO_TIME --> 针对localTime的格式化
DateTimeFormatter.ISO_DATE_TIME --> 针对localDateTime的格式化
下面的案例以 DateTimeFormatter.ISO_DATE_TIME 为例
DateTimeFormatter df1 = DateTimeFormatter.ISO_DATE_TIME;
LocalDateTime now = LocalDateTime.now();
// LocalDateTime --> String
String str = df1.format(now); // 2023-05-12T22:42:16.303
// String --> LocalDateTime
TemporalAccessor parse = df1.parse("2023-05-12T22:42:16.303"); // {},ISO resolved to 2023-05-12T22:42:16.303
1.1.5.4.2 本地化格式
如 ofLocalizedDateTime
参数:FormatStyle.LONG、FormatStyle.SHORT、FormatStyle.MEDIUM
DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
LocalDateTime now = LocalDateTime.now();
// localDateTime --> String
String format = df.format(now);
// String --> localDateTime
TemporalAccessor parse = df.parse("2023年5月17日 下午10时32分50秒");
System.out.println(parse);
FormatStyle.LONG: 2023年5月17日 下午10时32分50秒
FormatStyle.MEDIUM: 2023-5-17 22:35:40
FormatStyle.SHORT: 23-5-17 下午10:36
1.1.5.4.3 自定义格式化(用的最多)
ofPattern()
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
// localDatetime --> String
String format = df.format(now); // 2023-05-17 10:40:07
// String --> localDateTime
TemporalAccessor parse = df.parse("2023-05-17 10:40:07");
1.2 Math类
常用方法和属性
// 常用属性
System.out.println(Math.PI);
// 常用方法
System.out.println(Math.random()); // 随机数,取值范围为 [0,1)
System.out.println(Math.abs(-100)); // 绝对值,100
System.out.println(Math.ceil(3.1)); // 向上取值 4.0
System.out.println(Math.floor(3.9)); // 向下取值 3.0
System.out.println(Math.round(3.5)); // 四舍五入
System.out.println(Math.max(1, 2)); // 取最大值
System.out.println(Math.min(1, 2)); // 取最小值
静态导入 可以导入Math中的所有的静态属性和方法
import static java.lang.Math.*;
public class Main {
public static void main(String[] args) {
// 常用属性
System.out.println(PI);
// 常用方法
System.out.println(random()); // 随机数,取值范围为 [0,1)
System.out.println(abs(-100)); // 绝对值,100
System.out.println(ceil(3.1)); // 向上取值 4.0
System.out.println(floor(3.9)); // 向下取值 3.0
System.out.println(round(3.5)); // 四舍五入
System.out.println(max(1, 2)); // 取最大值
System.out.println(min(1, 2)); // 取最小值
}
public static int random(){
return 100;
}
}
注意此时的random函数走的是我们自己定义的这个
1.3 String类
1.3.1 String类的本质
String类是不可变的
String类是被final修饰的,不可以被继承
String底层是一个char类型的数组
1.3.2 构造器
String s1 = new String();
String s2 = new String("abc");
String s3 = new String(new char[]{'a', 'b', 'c'});
**补充**:数组定义的三种方式
int[] arr1 = new int[10];
int[] arr2 = new int[]{1,2};
int[] arr3 = {};
1.3.3 常用方法
| 方法名 | 作用 | 本质 |
|---|---|---|
| length() | 返回字符串的长度 | return value.length() |
| isEmpty() | 返回字符串是否为空 | return value.length() == 0 |
| charAt(int index) | 返回字符串索引为index的字符 | return value[index] |
| subString(int index) | 返回从index开始的截取的字符串 | |
| subString(int v1,int v2) | 返回下标在[v1,v2)范围截取的字符串 | |
| concat(String s) | 返回字符串和S拼接的结果 | "1".concat("2") // "12" |
| replace(char c1,char c2) | 把字符串中的c1改成c2 | |
| replace(CharSequence c1,CharSequence c2) | 把字符串中的c1改成c2 | String implements CharSequence |
| replaceFirst(String s1,String s2) | 把字符串的第一个s1替换成s2 |
1.3.4 equals源码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
1.3.5 compareTo源码
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
1.3.6 String内存分析
1、字符串拼接
public class Main {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "a"+"bc";
String s3 = "ab"+"c";
String s4 = "abc"+"";
}
}
编译之后如下图所示:原因为 进行了编译期优化。
public class Main {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = "abc";
String s4 = "abc";
}
}
内存分析如下
2、new String对象
new的对象会在堆中开辟出一块空间,这块空间的地址指向常量池中的“abc”,s5指向的是堆中的地址;s1,s2,s3以及s4指向的是常量池中的地址
3、字符串变量参与字符串拼接
public class Main {
public static void main(String[] args) {
String s1 = "abc";
String s2 = s1 + "def";
String s3 = "abcdef";
System.out.println(s2 == s3);
}
}
这个时候编译器不能识别出s1,不会进行编译期优化;想看到这个字节码文件的解析过程,我们可以使用 反编译。使用IDEA进行反编译如下:
由此可见,这个s2和s3的内存分析层面完全不一致,因此s2 != s3
1.3.7 StringBuilder
StringBuilder sb = new StringBuilder();
//表面上是在调用无参构造器,实际上是初始化了一个长度为16的字符数组
StringBuilder sb2 = new StringBuilder(4);
//表面上是在调用有参构造器,实际上是初始化了一个长度为 传入参数长度的数组
StringBuilder sb = new StringBuilder("abc");
// 1. 初始化长度为 3+16 的value字符数组
// 2. 把"abc"对应的value字符数组 复制到 长度为19的value字符数组
String的不可变性是指,在地址值不改变的情况下,String的值不能发生改变。StringBuilder是可变的是指,在地址值不发生改变的情况下,它的值可以改变的。
StringBuilder和StringBuffer的区别
StringBuilder是jdk1.5 开始出现的,效率高,线程不安全 StringBuffer是jdk1.0 始的,效率低,线程安全
1.4 集合
1.4.1 算法和数据结构
算法:
1、可以解决具体的问题 2、有设计解决问题的流程 3、有评价这个算法的具体指标(时间复杂度、空间复杂度)
数据结构:指计算机在硬盘、内存、缓存上面是如何组织管理数据的
1、逻辑结构-->思想上的结构-->线性表(数组、链表)、图、树、栈、队列 2、物理结构-->真实的结构-->紧密结构(顺序结构)和跳转结构(链式结构
1.4.2 简要集合结构图
1.4.3 Collection集合常用方法
| 方法名 | 作用 |
|---|---|
| add(E e) | 集合增加指定的元素 |
| addAll(Collection<? extends E> c) | 将指定集合中的所有元素增加到此集合中 |
| clear() | 删除集合中的所有元素 |
| remove(Object o) | 删除集合中存在的指定元素 |
| removeAll(Collecttion<?> c | 删除指定在集合中的元素 |
| iterator() | 返回此集合的迭代器 |
| size() | 返回集合中元素的个数 |
| contains(Object o) | 如果集合中存在此元素,返回true |
| contains(Collecttion<?> c | 如果此集合包含指定集合中的所有元素,返回true |
| equals(Object o) | 如果此集合和指定集合中的元素相同,返回true |
| isEmpty() | 如果此集合中没有元素,返回true |