一、Math
1、常用方法
abs
绝对值
abs(int i) / abs(float i) / abs(double i) / abs(long i)
int abs = Math.abs(-9);
System.out.println(abs);//9
pow
求幂
double pow = Math.pow(2, 4);//2的4次方
System.out.println(pow);//16
ceil
向上取整
返回>=该参数的最小整数(转成double);
double ceil = Math.ceil(3.9);
System.out.println(ceil);//4.0
floor
向下取整
返回<=该参数的最大整数(转成double)
double floor = Math.floor(4.001);
System.out.println(floor);//4.0
round
四舍五入
等价于 Math.floor(该参数+0.5)
double round1 = Math.round(-5.9);
long round2 = Math.round(5.51);
System.out.println(round1); //-6.0
System.out.println(round2);//6
sqrt
求开方
double sqrt = Math.sqrt(9.0);
System.out.println(sqrt);//3.0
random
求随机数
random 返回的是 0 <= x < 1 之间的一个随机小数
请写出获取 a-b之间的一个随机整数,a,b均为整数 ,比如 a = 2, b=7
即返回一个数 x -------- 其中2 <= x <= 7
(int)(a) <= x <= (int)(a + Math.random() * (b-a +1) )
⭐⭐⭐⭐
for (int i = 0; i < 100; i++) {
//取[2,7]范围的整数
System.out.println((int) (2 + Math.random() * (7 - 2 + 1)));
}
max , min
返回最大值和最小值
int min = Math.min(1, 9);
int max = Math.max(45, 90);
System.out.println("min=" + min); //1
System.out.println("max=" + max); //90
二、Date、Calendar、LocalDate
1、第一代日期类
1) Date
精确到毫秒,代表特定的瞬间;
//new Date() / new Date(long) : 获取当前系统时间
//1. 这里的Date 类是在java.util包
//2. 默认输出的日期格式是国外的方式, 因此通常需要对格式进行转换(SimpleDateFormat)
Date d1 = new Date(); //获取当前系统时间 //包:java.util.Date
System.out.println("当前日期=" + d1);
Date d2 = new Date(9234567); //通过指定毫秒数得到时间
System.out.println("d2=" + d2); //获取某个时间对应的毫秒数
2) SimpleDateFormat
格式和解析日期的类
SimpleDateFormat 格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。
// format : 将日期转换成指定格式的字符串
//1. 创建 SimpleDateFormat对象,可以指定相应的格式
//2. 这里的格式使用的字母是规定好,不能乱写
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
String format = sdf.format(d1);
System.out.println("当前日期=" + format);
//parse : 把一个格式化的String 转成对应的 Date(类型转换)
//1. 得到Date 仍然在输出时,还是按照国外的形式,如果希望指定格式输出,需要转换
//2. 在把String -> Date , 使用的 sdf 格式需要和你给的String的格式一样,否则会抛出转换异常
String s = "1996年01月01日 10:20:30 星期一";
Date parse = sdf.parse(s);
System.out.println("parse=" + sdf.format(parse));
2、第二代日期类
1)Calendar类(日历)
2)案例介绍
- Calendar是一个抽象类, 并且构造器是private
- 可以通过 getInstance() 来获取实例
Calendar c = Calendar.getInstance(); //创建日历类对象
System.out.println("c=" + c);
- 提供大量的方法和字段提供给程序员
//1.获取日历对象的某个日历字段
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH) + 1));//这里为什么要 + 1, 因为Calendar 返回月时候,是按照 0 开始编号
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("小时:" + c.get(Calendar.HOUR));
System.out.println("分钟:" + c.get(Calendar.MINUTE));
System.out.println("秒:" + c.get(Calendar.SECOND));
- Calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出(灵活)
System.out.println(c.get(Calendar.YEAR) + "-"
+ (c.get(Calendar.MONTH) + 1) + "-"
+ c.get(Calendar.DAY_OF_MONTH) + " "
+ c.get(Calendar.HOUR_OF_DAY) + ":"
+ c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) );
- 如果我们需要按照 24小时进制来获取时间,
Calendar.HOUR
==改成=>Calendar.HOUR_OF_DAY
System.out.println("小时:" + c.get(Calendar.HOUR_OF_DAY));
3、第三代日期类
1)前面两代日期类的不足分析
JDK1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK1.1引入Calendar类之后就被弃用了。而Calendar也存在问题是:
① 可变性:像日期和时间这样的类应该是不可变的;
② 偏移性:Date中的年份是从1900开始的,而月份都从0开始;
③ 格式化:格式化只对Date有用,Calendar则不行;
④ 此外,它们也不是线程安全的;不能处理闰秒等(每隔2天,多出1s)。
2)LocalDate(日期/年月日)、LocalTime(日期/时分秒)、LocalDateTime(日期/年月日时分秒)
这三个类是在JDK8加入的。
-
LocalDate
只包含日期,可以获取日期字段; -
LocalTime
只包含时间,可以获取时间字段; -
LocalDateTime
包含日期+时间,可以获取日期和时间字段
3)DateTimeFormatter 格式日期类
DateTimeFormat dtf = DateTimeFormatter.ofPattern(格式);
String str = dtf.format(日期对象);
4)重要方法
- 使用
now()
返回表示当前日期时间的 对象
LocalDate now1 = LocalDate.now(); //可以获取年月日
LocalTime now2 = LocalTime.now();//获取到时分秒
LocalDateTime now3 = LocalDateTime.now(); //可以获取到年月日时分秒
System.out.println(now1); //2023-07-20
System.out.println(now2); //10:33:57.391
System.out.println(now3); //2023-07-20T10:33:57.391
- 使用
getXXX
方法获取日期信息,并灵活排列
LocalDateTime ldt = LocalDateTime.now();
System.out.println("年=" + ldt.getYear());
System.out.println("月=" + ldt.getMonth());
System.out.println("月=" + ldt.getMonthValue());
System.out.println("日=" + ldt.getDayOfMonth());
System.out.println("时=" + ldt.getHour());
System.out.println("分=" + ldt.getMinute());
System.out.println("秒=" + ldt.getSecond());
- 使用
DateTimeFormatter
对象来进行格式化
LocalDateTime ldt = LocalDateTime.now();
// 创建 DateTimeFormatter对象
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = dateTimeFormatter.format(ldt);
System.out.println("格式化的日期=" + format);
- 提供
plus
和minus
方法可以对当前时间进行加或者减
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.now();
//看看890天后,是什么时候(输出:按照dateTimeFormatter格式输出"yyyy-MM-dd HH:mm:ss")
LocalDateTime localDateTime = ldt.plusDays(890);
System.out.println("890天后=" + dateTimeFormatter.format(localDateTime));
//890天后=2025-12-26 10:52:23
//看看在 3456分钟前是什么时候
LocalDateTime localDateTime2 = ldt.minusMinutes(3456);
System.out.println("3456分钟前 日期=" + dateTimeFormatter.format(localDateTime2));
//3456分钟前 日期=2023-07-18 01:16:23
5)Instant时间戳
类似于Date
提供了一系列和Date类的转换方式
- Instant----->Date:
Date date = Date.from(instant);
- Date----->Instant:
Instant instant = date.toInstant();
案例:
//通过静态方法now()获取表示当前时间戳的对象
Instant now = Instant.now();
System.out.println(now);
//通过from可以把Instant转成Date
Date date = Date.from(instant);
//通过toInstant可以把Instant转成Date
Instant instant = date.toInstant();
6)更多的方法
-
LocalDateTime类
-
MonthDay类:检查重复事件
-
是否为闰年;
-
增加日期的某个部分;
三、System
1)exit:退出当前程序
//exit 退出当前程序
System.out.println("ok1");
//1. exit(0) 表示程序退出
//2. 0 表示一个状态 , 正常的状态(主动退出)
System.exit(0);
System.out.println("ok2");
输出:
ok1
2)arraycopy:赋值数组元素,比较适合底层调用,一般使用Array.copyOf完成复制数组
int[] src = {1,2,3};
int[] dest = new int[3]; //[0,0,0]
System.arraycopy(src,0,dest,0,3);
System.out.println("dest=" + Arrays.toString(dest));//[1, 2, 3]
System.arraycopy(src,0,dest,1,2); //此时dest等于[1,2,3]
System.out.println("dest=" + Arrays.toString(dest));//[1,1,2]
五个参数说明:
srcPos
: 从源数组的哪个索引位置开始拷贝
dest
: 目标数组,即把源数组的数据拷贝到哪个数组
destPos
: 把源数组的数据拷贝到 目标数组的哪个索引
length
: 从源数组拷贝多少个数据到目标数组
System.arraycopy(src,0,dest,0,3);
从源数组src
的0
位置,拷贝到目标数组dest
的0
位置,拷贝3
个元素
3)currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
//currentTimeMillens:返回当前时间距离1970-1-1 的毫秒数
System.out.println(System.currentTimeMillis());
4)gc:运行垃圾回收机制 System.gc()
四、Arrays
1、常用方法
1)toString
//返回数组的字符串形式;
Integer[] integers = {1,20,90};
//直接使用Arrays.toString方法,显示数组
System.out.println(Arrays.toString(integers));//[1, 20, 90]
//不能用System.out.println(integers); //调用的是对象的toString方法,而不是Array的toString方法
2)sort
//排序(自然排序和定制排序);
- 可以直接使用冒泡排序 , 也可以直接使用Arrays提供的sort方法排序
- 因为数组是引用类型,所以通过sort排序后,会直接影响到 实参 arr
- sort重载,也可以通过传入一个接口 Comparator 实现定制排序
Integer arr[] = {1,-1,7,0,89};
- 自然排序
Arrays.sort(arr); // 默认排序方法
- 定制排序
调用 定制排序 时,传入两个参数:
(1) 排序的数组 arr
(2) 实现了Comparator接口的匿名内部类 , 要求实现 compare方法
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1; //返回大于0还是小于0,决定了数组的排序
}
});
- 排序后
System.out.println("===排序后===");
System.out.println(Arrays.toString(arr));
3)binarySearch
通过二分搜索法进行查找,要求必须排好序;
binarySearch(需要查找的数组 , 需要查找的元素值)
查找结果返回的是下标,如果不存在,则返回-(low+1)
// low:如果存在,满足有序条件时应该在的位置
Integer arr[] = {-1,1,0,8,89};
int index1 = Arrays.binarySearch(arr,3); //-4,如果3存在于这个有序数组,应该是在下标为3的位置,-(low+1) = -4
int index2 = Arrays.binarySearch(arr,8); //3
4)copyOf
数组元素的赋值;
Integer arr[] = {-1,1,0,8,89};
Integer[] newArr1 = Arrays.copyOf(arr,arr.length); //将arr中的arr.length个元素arr拷贝到newArr中
Integer[] newArr2 = Arrays.copyOf(arr,arr.length + 1); //如果复制长度大于原数组,则在后面添加null(空,不是"null"字符串)
Integer[] newArr3 = Arrays.copyOf(arr,-1); //如果复制长度<0,则抛出异常
System.out.println(Arrays.toString(newArr1)); //{-1,1,0,8,89};
System.out.println(Arrays.toString(newArr2)); //{-1,1,0,8,89,null};
System.out.println(Arrays.toString(newArr3)); //异常
5)fill
数组元素的填充;可以理解为替换所有元素
Integer[] arr = {-1,1,0,8,89};
Arrays.fill(arr, 99); //所有元素替换为99
System.out.println(Arrays.toString(arr));
6)equals
比较两个数组元素内容是否完全一致;
boolean equals = Arrays.equals(arr,arr2);
7)asList
将一组值,转换为list;
List<Integer> asList = Arrays.asList(2,3,4,5,6,1);
System.out.println("asList=" + asList);
2、练习
public class Test {
public static void main(String[] args){
Book[] books = new Book[4];
books[0] = new Book("西游记",100.9);
books[1] = new Book("简爱",108.8);
books[2] = new Book("三国演义",101.0);
books[3] = new Book("鲁滨逊漂流记",109.0);
//1. 根据价格降序排序
//Book.sort(books); //冒泡排序
Arrays.sort(books,new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Book book1 = (Book)o1;
Book book2 = (Book)o2;
//下面实现return r2 - r1的double变形(因为价格是double,compare返回值是int)
double dif = book2.getPrice() - book1.getPrice();
if(dif < 0) {
return -1; //r2 - r1 < 0
} else {
return 1; // r2 - r1 > 0
}
}
});
System.out.println(Arrays.toString(books));
//2. 根据书名长度,升序排序
Arrays.sort(books, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Book book1 = (Book)o1;
Book book2 = (Book)o2;
return book1.getName().length() - book2.getName().length();
}
});
System.out.println(Arrays.toString(books));
}
}
class Book {
private String name;
private double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
public double getPrice() {
return price;
}
public String getName() {
return name;
}
public static void sort(Book[] books){
for (int i = 0; i < books.length - 1; i++) {
for (int j = 0; j < books.length - i - 1; j++) {
if(books[j].price < books[j+1].price){
Book tmp = books[j];
books[j] = books[j+1];
books[j+1] = tmp;
}
}
}
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
五、BigInteger BigDecimal
1)BigInteger
适合保存比较大的整型
//当我们编程中,需要处理很大的整数,long 不够用
//可以使用BigInteger的类来搞定
//long l = 23788888899999999999999999999l;
//System.out.println("l=" + l);
BigInteger bigInteger = new BigInteger("23788888899999999999999999999");
BigInteger bigInteger2 = new BigInteger("10099999999999999999999999999999999999999999999999999999999999999999999999999999999");
System.out.println(bigInteger);
-
在对 BigInteger 进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
-
可以创建一个 BigInteger 用于接收加减乘除后的数。
-
进行相应操作的两个数也必须是BigInteger
BigInteger add = bigInteger.add(bigInteger2);
System.out.println(add);//加
BigInteger subtract = bigInteger.subtract(bigInteger2);
System.out.println(subtract);//减
BigInteger multiply = bigInteger.multiply(bigInteger2);
System.out.println(multiply);//乘
BigInteger divide = bigInteger.divide(bigInteger2);
System.out.println(divide);//除
2)BigDecimal
适合保存精度更高的浮点型(小数)
//当我们需要保存一个精度很高的数时,double 不够用
//可以是 BigDecimal
//double d = 1999.11111111111999999999999977788d;
//System.out.println(d);
BigDecimal bigDecimal = new BigDecimal("1999.11");
BigDecimal bigDecimal2 = new BigDecimal("3");
System.out.println(bigDecimal);
-
如果对 BigDecimal进行运算,比如加减乘除,需要使用对应的方法
-
创建一个需要操作的 BigDecimal 然后调用相应的方法即可
-
divide可能会抛出异常ArithmeticException(有可能除不尽,无限循环小数)
- 解决抛出异常的方法:指定精度(在一定位置就停止除法)
System.out.println(bigDecimal.add(bigDecimal2));
System.out.println(bigDecimal.subtract(bigDecimal2));
System.out.println(bigDecimal.multiply(bigDecimal2));
//System.out.println(bigDecimal.divide(bigDecimal2));//可能抛出异常ArithmeticException
//在调用divide 方法时,指定精度即可. BigDecimal.ROUND_CEILING
//如果有无限循环小数,就会保留 分子 的精度
System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));
六、(常用类)章作业
【第一题】
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入用户名:");
try {
String name = scanner.next();
Check.checkName(name);
break;
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
while (true) {
System.out.print("请输入密码:");
try {
String keyword = scanner.next();
Check.checkKeyword(keyword);
int key = Integer.parseInt(keyword);
break;
} catch (NumberFormatException e) {
System.out.println("密码必须全部为数字");
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
while (true) {
System.out.print("请输入邮箱:");
try {
String email = scanner.next();
Check.checkEmail(email);
System.out.println("注册成功");
break;
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
}
}
class Check {
public static void checkName(String name) {
if (!(name.length() >= 2 && name.length() <= 4)) {
throw new RuntimeException("用户名长度不正确");
}
}
public static void checkKeyword(String keyword) {
if (!(keyword.length() == 6)) {
throw new RuntimeException("密码长度不正确");
}
}
public static void checkEmail(String email) {
boolean isAt = false;
boolean isDot = false;
int indexAt = -1;
int indexDot = -1;
for (int i = 0; i < email.length(); i++) {
if (email.charAt(i) == '@' && isAt == false) {
isAt = true;
indexAt = i;
}
if (email.charAt(i) == '.' && isDot == false) {
isDot = true;
indexDot = i;
}
}
if (!(isAt && isDot && indexDot > indexAt)) {
throw new RuntimeException("邮箱必须包含@和. 且@在.前面");
}
}
}
【第二题】
【含有空格的键盘输入】—>scanner.nextLine();
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//String name = "Han Shun Ping";
System.out.print("请输入你的名字:");
String name = scanner.nextLine(); //这里不能用next(),next()不能接收空格
//方法1:split + format
printName1(name);
//方法2:indexOf + substring
printName2(name);
}
/**
* 1. 对输入的字符串进行校验
* 2. 对输入的字符串进行分割split(" ")
* 3. 对得到的String[]进行格式化
* @param str
*/
public static void printName1(String str) {
if(str == null) {
System.out.println("str不能为空");
return;
}
String[] names = str.split(" ");
if(names.length != 3) {
System.out.println("输入的字符串格式不对");
return;
}
//names[1]先全部转为大写,再取首字母
String format = String.format("%s,%s .%c", names[2],names[0],names[1].toUpperCase().charAt(0));
System.out.println(format);
}
public static void printName2(String name) {
int indexSpace1 = name.indexOf(" ");
int indexSpace2 = name.lastIndexOf(" ");
String s = name.substring(indexSpace2 + 1, name.length()) +
"," + name.substring(0, indexSpace1 + 1) +
"." + name.charAt(indexSpace1 + 1);
System.out.println(s);
}
}
【第三题】