Math类:数学工具类
- 私有化构造方法,所有方法是静态的(不用创建对象可以直接调用)
ceil向上取整
floor向下取整(看数轴)
统计两位自幂数和四叶玫瑰树
public class FourFlowers {
public static void main(String[] args) {
//统计两位的自幂数
int count1 = 0;
for (int i = 10; i <= 99; i++) {
int ge = i % 10;
int shi = i / 10;
double check = Math.pow(ge, 2) + Math.pow(shi, 2);
if (check == i) {
System.out.println("两位自幂数:" + i);
count1++;
}
}
System.out.println(count1);
System.out.println("-----------------------------------------");
//统计四叶玫瑰数字
int count2 = 0;
for (int i = 1000; i <= 9999; i++) {
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 100 % 10;
int qian = i / 1000 % 10;
double check = Math.pow(ge, 4) + Math.pow(shi, 4)+ Math.pow(bai, 4)+ Math.pow(qian, 4);
if (check == i) {
System.out.println("四位自幂数:" + i);
count2++;
}
}
System.out.println(count2);
}
}
System
提供了一些与系统相关的方法
- 时间原点:1970.1.1 0:0:0,我国在东八区,有8h时差
- 1s = 1000ms
- exit:停止虚拟机
- currentTimeMills:获取当前时间的毫秒值
- arraycopy:拷贝数组
我国处于东八区,差8h的时差
System.out.println(System.currentTimeMillis());//从C语言生日1970年一月一日到现在程序编译一共用了多少毫秒
Runtime
表示当前虚拟机的运行环境(方法不是静态的,所以想调用方法,必须先创建对象)
这样设计,Runtime只能有一个对象,即为java虚拟机的运行环境
用java代码监控虚拟机内存
//获得cpu的线程数,8
System.out.println(Runtime.getRuntime().availableProcessors());//8
//总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);//2002MB
//已经获取内存大小
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);//126MB
//剩余内存大小
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);//124MB,程序用了2M内存
//运行cmd命令
Runtime.getRuntime().exec("notepad");//打开记事本
Runtime.getRuntime().exec("shut -s -t 3600");//一小时后关机
Runtime.getRuntime().exec("shut -s -a");//取消关机
Object
- Object是java中的顶级父类,所以的类都直接或间接的继承于Object类
- Object类中的方法可以被所有子类访问,所以要学习Object类和其中的方法
toString方法:
表示返回对象的字符串表示形式
如果我们要打印一个对象,想要看到属性值的话,就重写toString方法,在重写的方法中把对象的属性值进行拼接
使用ptg插件右键直接生成JavaBean。会自动重写toString
public String toString() {
return "Cups{price = " + price + ", id = " + id + "}";
}
Cups cup = new Cups("100","a01");
System.out.println(cup);//System.out获取打印的对象,用cup调用重写的toString方法再打印出来(原来的toString方法打印的是包名+类名+@+地址值)
equals:
比较两个对象是否相等
- 如果没用重写equals方法,那么默认使用Object中的方法进行比较,比较的是地址值是否相等
- 一般来讲地址值对于实际意义不大,重写之后比较的就是对象内部的属性值
//重写之后的equals方法比较的就是对象内部的属性值
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cups cups = (Cups) o;
return Objects.equals(price, cups.price) && Objects.equals(id, cups.id);
}
大厂面试题
clone
对象克隆,把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象赋值
**浅克隆:**不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过类(默认浅克隆)
**深克隆:**基本数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的(如果需要 深克隆需要重写方法或者使用第三方工具类)
利用第三方工具深克隆
Objects
Objects是一个工具类,提供了一些方法去完成一些功能
Objects.equals(s1,s2)
- 方法的底层会判断s1是否为null,如果为null,直接返回false
- 如果s1不为null,那么就利用s1调用equals方法
- 此时s1是Student类型,所以最终还是会调用Student中的equals方法//如果没用重写,比较地址值,如果重写了,比较属性值
BigInteger
BigInteger表示一个大整数
在java中,整数有四种类型:byte、short、int、long
在底层占用字节个数:byte1个字节、short2个字节、int4个字节、long8个字节。
一个字节 = 8 个bit位
- BigInteger对象一旦创建,内部记录的值不能发生改变
- 字符串中必须是整数,否则会报错
- 获取指定进制的大整数,进制和整数数字必须吻合,二进制只能包含0和1
- 静态方法获取BigInteger的对象,内部有优化。
- 能表示范围比较小,只能在long的取值范围之内,如果超出long的范围就不行了。
- 在内部对常用的数字:-1616进行优化**。提前把-1616先创建好BigInteger对象,如果多次获取不会重新创建新的**
- BigInteger表示的数字没有超出long的范围,可以用静态方法获取,超出long的范围,可以用构造方法获取。
- 只要进行计算都会产生一个新的BigInteger对象
BigDecima
- 用于小数的精确计算
- 用来表示很大的小数
- 如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
- 如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
- 如果我们传递的是0~10之间的整数,包含0,包含10,那么方法会返回已经创建好的对象,不会重新new
正则表达式(RegularExpression)
regex正则表达式可以校验字符串是否满足一定的规则,并用来校验数据格式的合法性
在一段文本中查找满足要求的内容
//热线电话400-618-9090 1006184000
//热线电话的正则表达式:400-?[1-9]\\d{2}-?[1-9]{3}
//手机号码:15306159532
//一:1表示手机号码只能以1开头
//二:[3-9]表示手机号码第二位只能是3-9之间
//三:\\d{9}表示任意数字只可以出现9次
String regex1 = "1[3-9]\\d{9}";
if(input.matches(regex1)){
System.out.println("input" + "满足");
}else{
System.out.println("input" + "不满足");
}
//座机号码020-2324242
//一:区号 0\\d{2,3}
//0:表示区号一定是以0开头的
// \\d{2,3}:表示区号从第二位开始可以是任意数字,可以出现2到3次
//二:- ?表示次数,0次或一次
//三:号码 号码的第一位也不能以0开头,从第二位开始可以是任意的数字,号码的总长度:5-10位
String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
if(input.matches(regex2)){
System.out.println("input" + "满足");
}else{
System.out.println("input" + "不满足");
}
//邮箱号码323deei@pci.com.cn
//在书写邮箱号码正则的时候需要把正确的数据分位三部分
//第一部分: @的左边 \\w+ 表示任意的字母数字下划线,至少出现一次
//第二部分: @ 表示@只能出现一次
//第三部分:
// 3.1 .的左边 [\\w&&[^_]]{2,6} 表示任意的字母加数字,总共出现2-6次(排除了下划线)
// 3.2 . \\.
// 3.3 大写字母,小写字母都可以,只能出现2-3次 [a-zA-Z]{2,3}
// 我们可以把3.2和3.3看成一组,这一组可以出现1次或者两次
String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
System.out.println("3232323@qq.com".matches(regex3));
//24小时正则表达式 23:11:11 使用插件any-rule
String regex4 = "([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
//修改写法
String regex5 = "([01]\\d|2[0-3]):([0-5]\\d){2}";
//用户名要求:大小写字数,数字,下划线一共4-16位
String regex1 = "\\w{4,16}";
//18位,前17位任意数字,最后一位可以是数字可以是大写或小写的x
String regex1 = "[1-9]\\d{16}(\\d|x|X)";
//或者
String regex1 = "[1-9]\\d{16}(\\dxX)";
//或者
String regex1 = "[1-9]\\d{16}(\\d|(?!)x)";
//忽略abc的大小写
String regex = "(?i)abc";
//忽略bc的大小写
String regex1 = "a(?i)bc";
//忽略b的大小写
String regex2 = "a((?i)b)c";
//身份证号码的严格校验
//502235 2001 12 13 1375
//前面6位:省份,市区,派出所等信息 第一位不能是0,后面5位是 任意数字 [1-9]\\d{5}
//年的前半段: 18 19 20 (18|19|20)
//年的后半段: 任意数字出现两次 \\d{2}
//月份: 01~09 10 11 12 (0[1-9]|1[0-2])
//日期 01~31 (0[1-9]|[12]\\d|3[01])
//后面四位: 任意数字出现3次 最后一位可以是数字也可以是大写X或者小写x \\d{3}[\\dXx]
String regex = "[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]";
爬虫
Pattern:表示正则表达式
Matcher:文本匹配器,作用按照正则表达式的规则去读字符串,从头开始读取。在大串中去找符合匹配规则的子串
时间类
世界标准时间:格林尼治时间/格林威治时间(Greenwich Mean Time)简称GMT
目前世界标准时间(UTC)已经替换为:原子钟
中国标准时间:世界标准时间+8小时
时间单位换算:1s = 1000ms 1ms = 1000us 1us = 1000 ns
Date时间类
Date类是一个JDK写好的JavaBean类,描述时间,精确到毫秒
利用空参构造创建的对象,默认表示系统当前时间,利用有参构造创建的对象,表示指定时间
//创建对象表示一个时间
Date d = new Date();
System.out.println(d);
//创建对象表示一个指定的时间
//从时间原点开始过了0ms的时间
//东八区在基础时间上加8h
Date d2 = new Date(0L);//Thu Jan 01 08:00:00 CST 1970
System.out.println(d2);
//setTime修改时间
//1000ms = 1s
d2.setTime(1000L);
System.out.println(d2);
//getTime获取当前时间的毫秒值
long time = d2.getTime();
System.out.println(time);
private static void extracted() {
//打印时间原点开始一年之后的时间
Date date = new Date(0L);
long time = date.getTime();
time = time + 1000L * 60 * 60 * 24 * 365;
date.setTime(time);
System.out.println(date);
}
//定义任意两个Date对象,比较一下哪个时间在前,哪个时间在后
Random r = new Random();
Date d1 = new Date(r.nextInt());
Date d2 = new Date(r.nextInt());
long time1 = d1.getTime();
long time2 = d2.getTime();
if (time1 >time2){
System.out.println(d1+"时间后于" + d2);
}else if(time1 <time2){
System.out.println(d1+"时间先于" + d2);
}else{
System.out.println("两者时间相同");
}
}
SimpleDateFormat类作用
- **格式化:**把时间变成熟悉的格式
- **解析:**把字符串表示的时间变成Date对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zyvnkZK-1673073119859)(C:\Users\86152\AppData\Roaming\Typora\typora-user-images\image-20230105113150295.png)]
字母 日期或时间元素 表示 示例 G
Era 标志符 Text AD
y
年 Year 1996
;96
M
年中的月份 Month July
;Jul
;07
w
年中的周数 Number 27
W
月份中的周数 Number 2
D
年中的天数 Number 189
d
月份中的天数 Number 10
F
月份中的星期 Number 2
E
星期中的天数 Text Tuesday
;Tue
a
Am/pm 标记 Text PM
H
一天中的小时数(0-23) Number 0
k
一天中的小时数(1-24) Number 24
K
am/pm 中的小时数(0-11) Number 0
h
am/pm 中的小时数(1-12) Number 12
m
小时中的分钟数 Number 30
s
分钟中的秒数 Number 55
S
毫秒数 Number 978
z
时区 General time zone Pacific Standard Time
;PST
;GMT-08:00
Z
时区 RFC 822 time zone -0800
ic static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date(0L);
String s = sdf.format(date);
//1970/1/1 上午8:00
System.out.println("默认格式为:"+ s);
//1970年01月01日 08:00:00 周四
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EE");
String s2 = sdf2.format(date);
System.out.println(s2);
String str = "2023-1-6 10:07:08 周五";
//创建对象的格式要跟字符串的格式完全一致
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EE");
Date date = sdf2.parse(str);
System.out.println(date.getTime());
String str = "2000-10-13";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf1.parse(str);
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(sdf2.format(date));
String startTime = "2023-01-06 10:27";
String endTime = "2023-01-06 11:27";
String orderTime1 = "2023-01-06 11:00";
String orderTime2 = "2023-01-06 12:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date startDate = sdf.parse(startTime);
Date endDate = sdf.parse(endTime);
Date orderDate1 = sdf.parse(orderTime1);
Date orderDate2 = sdf.parse(orderTime2);
if (orderDate1.getTime() > startDate.getTime() && orderDate1.getTime() < endDate.getTime()){
System.out.println(orderTime1+"在时间范围内");
}else{
System.out.println(orderTime1+"不在时间范围内");
}
if (orderDate2.getTime() > startDate.getTime() && orderDate2.getTime() < endDate.getTime()){
System.out.println(orderTime2+"在时间范围内");
}else{
System.out.println(orderTime2+"不在时间范围内");
}
Calendar
- Calendar代表了系统当前时间的日历对象,可以单独修改、获取时间中的年、月、日
- 细节:Calendar是一个抽象类,不能直接创建对象
Calendar是一个抽象类,不能直接new,而是通过一个静态方法获取到子类对象
底层原理:
会根据系统的不同时区来获取不同的日历对象,默认表示当前时间
会把时间中的纪元,年,月,日,时,分,秒,星期,等待都放到一个数组当中
索引: 0:纪元 1:年 2:月 3:一年中的第几周 4:一个月中的第几周 5:一个月中的第几天
月份:范围0~11 如果获取出来的是0,那么实际是1月
星期:星期日是一周中第一天
1(星期日) 2(星期一) 3(星期二) 4(星期三) 5(星期四) 6(星期五) 7(星期六)
Calendar c = Calendar.getInstance();
Date date = new Date(0L);
c.setTime(date);
System.out.println(c);
Calendar c = Calendar.getInstance();
Date date1 = new Date(0L);
c.setTime(date1);
System.out.println(c);
c.set(Calendar.YEAR,2023);
c.set(Calendar.MONTH,0);
c.set(Calendar.DATE,6);
c.add(Calendar.MONTH,-1);//2022,12,6,星期二
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DATE);
int week = c.get(Calendar.WEEK_OF_MONTH);//2023,1,6,星期一
System.out.println(year + "," + month + "," + date + "," + getWeek(week));
}
private static String getWeek(int index) {
String[] arr = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
return arr[index];
}
JDK新增时间相关类
//获取Java中支持的所有时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds);
System.out.println(zoneIds.size());//600
//获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
//获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Shanghai");
System.out.println(zoneId1);
//指定时区 方法非静态,用对象调用
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(time);
//isXxx判断
Instant instant4 = Instant.ofEpochMilli(0L);
Instant instant5 = Instant.ofEpochMilli(1000L);
//时间判断
System.out.println(instant4.isAfter(instant5));
System.out.println(instant4.isBefore(instant5));
//根据(秒/毫秒/纳秒)获取Instant对象,方法为静态,用类名调用
Instant instant6 = Instant.ofEpochMilli(3000L);//1970-01-01T00:00:03Z
System.out.println(instant6);
//Instant minusXxx(long millisToSubtract)减少时间系列的方法
Instant instant7 = instant6.minusSeconds(1);//1970-01-01T00:00:02Z
System.out.println(instant7);
JDK8新增的时间对象都是不可变的,如果我们修改了,减少了,增加了时间,那么调用者是不会发生改变,而是产生一个新的时间
包装类
基本数据类型对应的引用数据类型
/*键盘录入一些1~100之间的整数,并添加到集合中
直到集合中所有数据和超过200为止*/
Random r = new Random();
ArrayList<Integer> list = new ArrayList<>();
int sum = 0;
while (true) {
int i = r.nextInt(201);
list.add(i);
for (int i1 = 0; i1 < list.size(); i1++) {
sum += list.get(i1);
}
if(sum > 200){
System.out.println("和为" + sum);
System.out.println(list);
break;
}
}
ArrayList<Integer> list = new ArrayList<>();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入一个整数");
String numStr = sc.nextLine();
int num = Integer.parseInt(numStr);
//过滤异常数据
if(num <1 || num >100){
System.out.println("输入数据有误!请重新输入");
continue;
}
//num为基本数据类型,集合里面数据是Integer
//添加数据的时候触发了自动装箱
list.add(num);
int sum = getSum(list);
if(sum > 200){
System.out.println("已经满足要求!");
break;
}
}
System.out.println(list);
}
private static int getSum(ArrayList<Integer> list) {
int sum = 0 ;
for (int i = 0; i < list.size(); i++) {
//自动拆箱
sum += list.get(i);
}
return sum;
}
while (true) {
System.out.println("请输入一个只包含数字的10位字符串,首字母不能为0");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String regex = "[1~9]\\d{9}";
if (str.matches(regex)) {
// System.out.println(Integer.parseInt(str));
int num = 0;
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i) - '0';
num = num*10 + c;
}
System.out.println(num);
break;
}else{
System.out.println("输入不正确,请重新输入!");
}
}
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个十进制数");
String s = sc.nextLine();
// String s1 = Integer.toBinaryString(Integer.parseInt(s));
// System.out.println(s1);
String str = toBinaryString(s);
System.out.println(str);
}
private static String toBinaryString(String s) {
int i = Integer.parseInt(s);
int yu;
StringBuilder sb = new StringBuilder();
while (true) {
if (i == 0) {
break;
}
yu = i % 2;
sb.append(yu);
//sb.insert(0,i)
i = i / 2;
System.out.println(yu);
}
return sb.reverse().toString();
}
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的生日:yyyy年MM月dd日");
String birthday = sc.nextLine();
long liveDays1 = jdk7Cheak(birthday);
long liveDays2 = jdk8Cheak(birthday);
System.out.println("jdk7的方法活了" + liveDays1 + "天数");
System.out.println("jdk8的方法活了" + liveDays2 + "天数");
}
private static long jdk8Cheak(String birthday) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date birthdayDate = sdf.parse(birthday);
int year = birthdayDate.getYear()+1900;
System.out.println(year);
int month = birthdayDate.getMonth()+1;
System.out.println(month);
int day = birthdayDate.getDay()+8;
System.out.println(day);
LocalDate ld1 = LocalDate.of(year, month,day);
LocalDate ld2 = LocalDate.now();
long days = ChronoUnit.DAYS.between(ld1,ld2);
return days;
}
private static long jdk7Cheak(String birthday)throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date birthdayDate = sdf.parse(birthday);
long birthdayDateTime = birthdayDate.getTime();
long currentMills = System.currentTimeMillis();
long time = currentMills - birthdayDateTime;
return time / 1000 / 3600 / 24;
}
//四年闰,百年不闰,四百年闰
Scanner sc = new Scanner(System.in);
System.out.println("请输入需要判断闰年的年份:");
String yearStr = sc.nextLine();
int year = Integer.parseInt(yearStr);
if (checkYear(year)) {
System.out.println(year + "是闰年");
} else {
System.out.println(year + "不是闰年");
}
System.out.println("isLeapYear()方法判断:" + LocalDate.of(year, 2, 2).isLeapYear());
}
private static boolean checkYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return true;
}else {
return false;
}
}