目录
1.常用API
①StringBuilder、StringBuffer
StringBuilder代表可变字符串对象,相当于是一个容器,它里面装的字符串是可以改变的,就是用来操作字符串的。
好处:StringBuilder比String更适合做字符串的修改操作,效率会更高,代码也会更简洁。
StringBuffer的用法与StringBuilder是一模一样的,但 StringBuilder是线程不安全的 StringBuffer是线程安全的
//1、创建StringBuilder对象
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder("吕布");
System.out.println(sb);
System.out.println(sb2);
//2、拼接内容
sb2.append("骑").append("赤兔");
System.out.println(sb2);
//3、反转内容
sb2.reverse();
System.out.println(sb2);
//4、拿长度
System.out.println(sb2.length());
//5、把StringBuilder对象转换成String对象
//StringBuilder是拼接字符串的手段
//String才是开发中的目的
String s = sb2.toString();
System.out.println(s);
StringBuilder和String拼接字符串性能测试
public static void main(String[] args) {
//StringBuilder和String拼接字符串性能测试
//使用String
/*String s = "";
for (int i = 0; i < 100000; i++) {
s += "ABC";
}
System.out.println(s); 运行结果很慢,因为String是不可变对象,频繁操作字符串会产生很多垃圾对象,性能差*/
//使用StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append("ABC");
}
System.out.println(sb); //运行结果很快,StringBuilder是内存可变的字符串。知道内存不够,会自动开辟一个大的空间
}
对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler,效率更高!
注意:如果操作字符串较少,或者不需要操作,以及定义字符串变量,还是建议用String。
②StringJoiner
概念:JDK8才开始有的,跟StringBuilder一样,也是用来操作字符串的,可以看成一个容器,创建后里面的内容是可变的
好处:不仅可以提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁
使用StringBuilder写一个对字符串的拼接操作的方法
public static String getArratData(int[] arr){
if (arr == null){
return null;
}
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
int data = arr[i];
sb.append(data).append(i == arr.length -1 ?"":", ");
}
sb.append("]");
return sb.toString();
}
使用StringJoiner写一个对字符串的拼接操作的方法
public static String getArratData(int[] arr){
if (arr == null){
return null;
}
//参数一:间隔符号、参数二:开始符号、参数三:结束符号
StringJoiner sb = new StringJoiner(", ","[","]");
for (int i = 0; i < arr.length; i++) {
sb.add(Integer.toString(arr[i])); //他只能加String类型,要转换
}
return sb.toString();
}
③Math、System、
Math、System都是静态方法,属于工具类
System.out.println(Math.abs(-12)); // 12 绝对值
System.out.println(Math.ceil(4.0000001)); // 5.0 向上取整
System.out.println(Math.floor(4.999999)); // 4.0 向下取整
System.out.println(Math.round(3.4999)); // 3 四舍五入
System.out.println(Math.max(10, 20)); // 20 两个数求较大值
System.out.println(Math.min(10, 20)); // 10 两个数求较小值
System.out.println(Math.pow(2, 3)); // 2的3次方 8.0 求次方
System.out.println(Math.random()); //取随机数 [0.0 , 1.0) (包前不包后)
long time = System.currentTimeMillis(); // 获取系统的时间毫秒值。
System.out.println(time);
// 可以做性能统计
for (int i = 0; i < 1000000; i++) {
System.out.println(i);
}
long time2 = System.currentTimeMillis(); // 获取系统的时间毫秒值。
System.out.println((time2 - time) / 1000.0 + "s"); //这个时间到刚才计算的时候的差值,就是中间代码的运行时间
public static long currentTimeMillis():返回的是从1970-1-1 00:00:00 走到此刻的总毫秒值(1s = 1000ms)
④Bigdecimal
用于解决浮点型运算时,出现结果失真的问题
public static void main(String[] args) {// 浮点型运算时, 直接+ - * / 可能会出现运算结果失真
System.out.println(0.1 + 0.2); 结果0.30000000000000004
}
因为计算机底层是二进制计算,首先会把0.1和0.2转成二进制,然后再进行运算,有的会出现失真(有的小数转成二进制是无限循环的)
1、把两个数据包装成BigDecimal对象
// public BigDecimal(String val):这个接收字符串的构造器才可以处理失真问题
// public BigDecimal(double val):这个只是让精度位数更多,不能解决精度问题
BigDecimal a1 = new BigDecimal(Double.toString(a));//所以把a转成字符串
BigDecimal b1 = new BigDecimal(Double.toString(b));
// b、阿里巴巴公司更推荐我们使用valueOf方法包装浮点型数据成 BigDecimal对象
// 跟上面的做法本质是一样的
BigDecimal a2 = BigDecimal.valueOf(a);
BigDecimal b2 = BigDecimal.valueOf(b);
//2、调用方法进行精度计算
BigDecimal c2 = a2.add(b2); // add 加法
BigDecimal c22 = a2.subtract(b2); // subtract 减法
BigDecimal c222 = a2.multiply(b2); // multiply 乘法
BigDecimal c2222 = a2.divide(b2); // divide 除法
//3、BigDecimal是处理精度问题的手段,结果必须还是基本类型(是目的)
double result = c2.doubleValue();
System.out.println(result);
System.out.println("---------------------------");
BigDecimal i =BigDecimal.valueOf(0.1);
BigDecimal j =BigDecimal.valueOf(0.3);
//BigDecimal k = i.divide(j); //BigDecimal是要返回精确的结果,但三分之一无法精确
/*参数一:除数
* 参数二:保留位数
* 参数三:舍入模式(输入RoundingMode. 就可以看到)
* RoundingMode.HALF_UP四舍五入,RoundingMode.HALF_UP向上取整等
* */
BigDecimal t = i.divide(j,2, RoundingMode.HALF_UP);
System.out.println(t);
2.常用API(二)
①Arrays
用来操作数组的一个工具类。
public static void main(String[] args) {
//Arrays的常见方法。
//1、返回数组内容:public static String(类型[] a)
int[] arr = {11,55,33,22,98};
String result = Arrays.toString(arr);
System.out.println(result);
//2、拷贝数组的内容到一个新的数组,并返回新数组
//public static 类型[] copyOfRange(类型[] original,int from,int to)
int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
System.out.println(Arrays.toString(arr2));
//3、给数组扩容
int[] ints = Arrays.copyOf(arr, 5);
System.out.println(Arrays.toString(ints));
//4、修改数组中的每个数据,再存入
double[] scores = {55,99,44,66,35};
//需求:为每个分数加10分
Arrays.setAll(scores, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int index) {
return scores[index] + 10;
}
});
System.out.println(Arrays.toString(scores));
//5、Arrays类提供的对数组进行排序的操作
Arrays.sort(scores); //升序 ,由小到大
System.out.println(Arrays.toString(scores));
}
②arrays自定义排序
sort方法是比较有明显顺序的值,但是我们在开发过程中处理的大多都是对象,对象没有明确的规则进行排序
public class Student implements Comparable<Student>{
private String name;
private int age;
private char gender;
private double height;
get、set方法,有参无参构造器,toString()
//指定大小规则
//比较者:this
//被比较者:o
@Override
public int compareTo(Student o) {
/*官方规定:
* 如果您认为左边大于右边,请返回正整数
* 如果您认为右边大于左边,请返回负整数
* 如果您认为左边小于右边,请返回负整数
* 这样写默认是升序
* */
/* if (this.age > o.age){
return 1;
} else if (this.age < o.age) {
return -1;
}
return 0; 这样写很low
*/
//return this.age - o.age; //如果左>右就是正数 ,升序
return o.age - this.age ; //降序
}
}
public static void main(String[] args) {
Student[] students = new Student[4];
students[0] = new Student("周芷茉", 33, '女', 169.3);
students[1] = new Student("张无忌", 24, '男', 172.2);
students[2] = new Student("小昭", 19, '女', 168.5);
students[3] = new Student("殷素素", 23, '男', 183.5);
//自定义排序规则方式一:让对象所在的类实现比较规则接口Comparable,重写compareTo方法,来指定比较规则
Arrays.sort(students);
System.out.println(Arrays.toString(students));
System.out.println("----------------------------------");
//自定义排序规则方式二:sort存在重载的方法,支持自带的Comparator比较器对象来直接指定比较规则
//public static <T> void sort(T[] a,Comparator<? super T> c)
Arrays.sort(students, new Comparator<Student>() { //如果两个规则都有,优先用这个,因为就近原则
@Override
public int compare(Student o1, Student o2) {
//return o1.getHeight() - o2.getHeight();
/*if (o1.getHeight() > o2.getHeight()){ //比较小数,因为返回了类型是int,所以就老实写
return 1;
} else if (o1.getHeight() < o2.getHeight()) {
return -1;
}else {
return 0;
}*/
return Double.compare(o1.getHeight(),o2.getHeight()); //包装类里面源码是和上面的代码差不多,大于也是返回1
}
});
System.out.println(Arrays.toString(students));
}
③lambda
主要是为了简化匿名内部类代码
注意:只能简化函数式接口的,有@FunctionalInterface标识的都是函数式接口
函数式接口他的特点是:有且只有一个抽象方法
public static void main(String[] args) {
Swimming s1 = new Swimming() {
@Override
public void swim() {
System.out.println("学生🏊贼溜");
}
};
s1.swim();
System.out.println("---------------------");
//简化形式
Swimming s2 = () ->{
System.out.println("学生🏊贼溜");
};
s2.swim();
}
}
@FunctionalInterface
interface Swimming{
void swim(); //多一个方法就报错(函数式接口)
}
abstract class Animal{
public abstract void run();
}
public static void main(String[] args) {
double[] scores = {55,99,44,66,35};
Arrays.setAll(scores, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int index) {
return scores[index] + 10;
}
});
//简化形式有@FunctionalInterface,就可以进行简化
Arrays.setAll(scores, (int index) -> {
return scores[index] + 10;
});
/*进一步简化写法:
* 参数类型可以省略不写
* 如果只有一个参数,参数类型可以省略,同时()也可以省略
* 如果Lambda表达式中的方法体只有一行代码,可以省略大括号不写,省略分号
* 如果这行代码式return语句,也必须去掉return不写
* */
//继续简化。参数类型可以省略,同时()也可以省略
Arrays.setAll(scores, index -> {
return scores[index] + 10;
});
//进一步简化
Arrays.setAll(scores, index -> scores[index] + 10);
System.out.println(Arrays.toString(scores));
System.out.println("----------------------------------------------------");
Student[] students = new Student[4];
students[0] = new Student("周芷茉", 33, '女', 169.3);
students[1] = new Student("张无忌", 24, '男', 172.2);
students[2] = new Student("小昭", 19, '女', 168.5);
students[3] = new Student("殷素素", 23, '男', 183.5);
Arrays.sort(students, (Student o1, Student o2)-> {
return Double.compare(o1.getHeight(),o2.getHeight());
});
//简化
Arrays.sort(students, (o1, o2)-> Double.compare(o1.getHeight(),o2.getHeight()));
System.out.println(Arrays.toString(students));
}
④方法引用
静态方法的引用 格式 -> 类名::静态方法
使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且前后参数一致,就可以使用静态方法引用
public class Student implements Comparable<Student>{
private String name;
private int age;
private char gender;
private double height;
get、set、有参、无参、toString方法
public static int compareByHeight(Student o1,Student o2){
return Double.compare(o1.getHeight(),o2.getHeight())}
}
public static void main(String[] args) {
Student[] students = new Student[4];
students[0] = new Student("周芷茉", 33, '女', 169.3);
students[1] = new Student("张无忌", 24, '男', 172.2);
students[2] = new Student("小昭", 19, '女', 168.5);
students[3] = new Student("殷素素", 23, '男', 183.5);
Arrays.sort(students, (o1, o2)-> Double.compare(o1.getHeight(),o2.getHeight()));
//简化后
Arrays.sort(students,Student::compareByHeight);
}
实例方法的引用 格式 -> 类名::实例方法
使用场景:如果某个Lambda表达式里只是调用一个实例方法,并且前后参数一致,就可以使用实例方法引用
public class Test2 {
public static void main(String[] args) {
Student[] students = new Student[4];
students[0] = new Student("周芷茉", 33, '女', 169.3);
students[1] = new Student("张无忌", 24, '男', 172.2);
students[2] = new Student("小昭", 19, '女', 168.5);
students[3] = new Student("殷素素", 23, '男', 183.5);
Arrays.sort(students, (o1, o2)-> Double.compare(o1.getHeight(),o2.getHeight()));
//终极简化
Test2 t = new Test2();
//Arrays.sort(students,(o1, o2)->t.compare(o1,o2)); 前后参数一致
Arrays.sort(students,t::compare);
System.out.println(Arrays.toString(students));
}
public int compare(Student o1,Student o2){
return Double.compare(o1.getHeight(),o2.getHeight());
}
}
特定类型的方法引用 格式 -> 类型::方法
使用场景:如果只是调用一个实例方法,并且前面参数列表的第一个参数作为方法的主调,那么后面的所以参数读书该实例方法的入参的
则可以使用特定类型引用
public static void main(String[] args) {
//特定类型的方法引用
String[] names = {"dlei","baby","Angela","cao","曹操"}; //这种用传统的排序是无法排的
//对他们进行排序(默认按照首字母编号排序)
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2); //忽略大小写比较
}
});
Arrays.sort(names,(o1,o2) -> o1.compareToIgnoreCase(o2));
//简化
Arrays.sort(names,String::compareToIgnoreCase);
}
构造器引用
具体遇到会有示例代码
⑤排序算法
冒泡排序:把两两比较把较大者放到最后
public class BubbleSortDemo1 {
public static void main(String[] args) {
//1、创建一个数组
int[] arrs = {2, 5, 1, 3};
//2、排序操作
for (int i = 0; i < arrs.length - 1; i++) {
// 轮数(i) 每轮的次数 j的占位 找规律
// 第一轮 i=0 3 0 1 2
// 第二轮 i=1 2 0 1
// 第三轮 i=2 1 0
//3、控制内循环的次数
for (int j = 0; j < arrs.length - i - 1; j++) {
if (arrs[j] >arrs[j+1]){
int temp = arrs[j+1];
arrs[j+1] = arrs[j];
arrs[j] = temp;
}
}
}
System.out.println(Arrays.toString(arrs));
}
}
选择排序:每轮选择当前位置,开始找出后面的较小值与该位置交换
public class SelectionSortDemo2 {
public static void main(String[] args) {
//1、创建一个数组
int[] arrs = {2, 5, 1, 3};
//2、排序操作(这种每次都要换位置,性能较差)
for (int i = 0; i <arrs.length - 1; i++) {
// 轮数(i) 每轮的次数 j的占位
// 第一轮 i=0 3 1 2 3
// 第二轮 i=1 2 2 3
// 第三轮 i=2 1 3
for (int j = i + 1; j < arrs.length; j++) {
//3、判断j对应位置处的数据是否小于当前i位置的数据,小于就交换
if (arrs[j] < arrs[i]){
int temp = arrs[i];
arrs[i] = arrs[j];
arrs[j] = temp;
}
}
}
System.out.println(Arrays.toString(arrs));
}
}
public class SelectionSortDemo2_2 {
public static void main(String[] args) {
//1、创建一个数组
int[] arrs = {2, 5, 1, 3};
//2、排序操作(性能较好)
for (int i = 0; i <arrs.length - 1; i++) {
// 轮数(i) 每轮的次数 j的占位
// 第一轮 i=0 3 1 2 3
// 第二轮 i=1 2 2 3
// 第三轮 i=2 1 3
//定义一个变量记住这一轮最小值对应的索引
int min = i;
for (int j = i + 1; j < arrs.length; j++) {
//3、判断j对应位置处的数据是否小于当前i位置的数据,
if (arrs[j] < arrs[min]){
min = j;
}
}
if (min !=i){
int temp = arrs[i];
arrs[i] = arrs[min];
arrs[min] = temp;
}
}
System.out.println(Arrays.toString(arrs));
}
}
二分查找:对数据进行折半进行查找
前提:数据必须是有序的,才能折半
因为是独立功能,所以独立成方法
public class BinarySearchDemo3 {
public static void main(String[] args) {
//1、准备数据
int[] arrs = {7, 23, 79, 81, 103, 127, 131, 147};
int index = searchDataIndex(arrs, 79);
int index2 = searchDataIndex(arrs, 179);
System.out.println("索引是:" + index);
System.out.println("索引是:" + index2);
}
public static int searchDataIndex(int[] array, int number) {
//1、定义头尾指针
int left = 0;
int right = array.length - 1;
while (left <= right) { //找不到左边就不会小于右边
//2、取中间索引值
int middle = (left + right) / 2;
//3、判断当前要找的数据,与中间位置处的数据大小情况
if (number > array[middle]) {
//4、从左往右边找,左边指针更新为中间位置+1
left = middle + 1;
} else if (number < array[middle]) {
//4、从右往左边找,右边指针更新为中间位置-1
right = middle - 1;
}else {
return middle;
}
}
return -1;//代表没找到
}
}
⑥正则表达式
就是由一些特定的字符组成,代表的是一个规则
作用一:用来校验数据格式是否合法
作用二:在一段文本中查找满足要求的内容
public class RegexTest1 {
public static void main(String[] args) {
System.out.println(checkQQ("1210121022"));
System.out.println(checkQQ("1210aaa121022"));
}
//需求:要求校验qq号,必须是5位及以上,全部是数字,不能以0开头
public static boolean checkQQ(String qq){
return qq!=null&&qq.matches("[1-9]\\d{4,}");
} //String提供了matches方法,判断字符串是否匹配正则表达式,匹配返回true,不匹配返回false
//常规写法:
/*public static boolean checkQQ(String qq){
if (qq == null || qq.startsWith("0")||qq.length() <5){
return false;
}
for (int i = 0; i < qq.length(); i++) {
char ch = qq.charAt(i);
if (ch > '9' || ch<'0'){
return false;
}
}
return true;
}*/
}
正则表达式匹配规则
public class RegexTest2 {
public static void main(String[] args) {
// 1、字符类(只能匹配单个字符)
System.out.println("a".matches("[abc]")); // [abc]只能匹配a、b、c
System.out.println("e".matches("[abcd]")); // false
System.out.println("d".matches("[^abc]")); // [^abc] 不能是abc
System.out.println("a".matches("[^abc]")); // false
System.out.println("b".matches("[a-zA-Z]")); // [a-zA-Z] 只能是a-z A-Z的字符
System.out.println("2".matches("[a-zA-Z]")); // false
System.out.println("k".matches("[a-z&&[^bc]]")); // : a到z,除了b和c
System.out.println("b".matches("[a-z&&[^bc]]")); // false
System.out.println("ab".matches("[a-zA-Z0-9]")); // false 注意:以上带 [内容] 的规则都只能用于匹配单个字符
// 2、预定义字符(只能匹配单个字符) . \d \D \s \S \w \W
System.out.println("徐".matches(".")); // .可以匹配任意字符
System.out.println("徐徐".matches(".")); // false
// 在Java中,\是有特殊用途的,一般作为特殊字符使用不能独立存在:\n \t
// \需要再使用\转义
System.out.println("2".matches("\\d")); // true
System.out.println("a".matches("\\d")); // false
System.out.println(" ".matches("\\s")); // \s: 代表一个空白字符
System.out.println("a".matches("\s")); // false
System.out.println("a".matches("\\S")); // \S: 代表一个非空白字符
System.out.println(" ".matches("\\S")); // false
System.out.println("a".matches("\\w")); // \w: [a-zA-Z_0-9]
System.out.println("_".matches("\\w")); // true
System.out.println("徐".matches("\\w")); // false
System.out.println("徐".matches("\\W")); // [^\w]不能是a-zA-Z_0-9
System.out.println("a".matches("\\W")); // false
System.out.println("23232".matches("\\d")); // false 注意:以上预定义字符都只能匹配单个字符。
// 3、数量词: ? * + {n} {n, } {n, m}
System.out.println("a".matches("\\w?")); // ? 代表0次或1次
System.out.println("".matches("\\w?")); // true
System.out.println("abc".matches("\\w?")); // false
System.out.println("abc12".matches("\\w*")); // * 代表0次或多次
System.out.println("".matches("\\w*")); // true
System.out.println("abc12张".matches("\\w*")); // false
System.out.println("abc12".matches("\\w+")); // + 代表1次或多次
System.out.println("".matches("\\w+")); // false
System.out.println("abc12张".matches("\\w+")); // false
System.out.println("a3c".matches("\\w{3}")); // {3} 代表要正好是n次
System.out.println("abcd".matches("\\w{3}")); // false
System.out.println("abcd".matches("\\w{3,}")); // {3,} 代表是>=3次
System.out.println("ab".matches("\\w{3,}")); // false
System.out.println("abcde徐".matches("\\w{3,}")); // false
System.out.println("abc232d".matches("\\w{3,9}")); // {3, 9} 代表是 大于等于3次,小于等于9次
// 4、其他几个常用的符号:(?i)忽略大小写 、 或:| 、 分组:()
System.out.println("----------------------------------------------------");
System.out.println("abc".matches("(?i)abc")); // true
System.out.println("ABC".matches("(?i)abc")); // true
System.out.println("aBc".matches("a((?i)b)c")); // true
System.out.println("ABc".matches("a((?i)b)c")); // false
// 需求1:要求要么是3个小写字母,要么是3个数字。
System.out.println("123".matches("(\\d{3})|([a-z]{3})"));
System.out.println("abc".matches("(\\d{3})|([a-z]{3})"));
System.out.println("ab1".matches("(\\d{3})|([a-z]{3})"));
// 需求2:必须是”我爱“开头,中间可以是至少一个”编程“,最后至少是1个”666“
System.out.println("我爱编程编程666666".matches("我爱(编程)+(666)+"));
System.out.println("我爱编程编程6666666".matches("我爱(编程)+(666)+"));
}
}
3.异常
①异常就是代表程序出现的问题
Error:代表的系统级别错误(属于严重问题),也就是说系统一旦出现问题,sun公司会把这些问题封装成Error对象给出来, 说白了,Error是给sun公司自己用的,不是给我们程序员用的,因此我们开发人员不用管它。
Exception:叫异常,它代表的才是我们程序可能出现的问题,所以,我们程序员通常会用Exception以及它的孩子来封装程序出现的问题。
抛出异常(throws)
方法 throws 异常1,异常2{
……
}
捕获异常(try……catch)
try{
//监视可能出现的异常得到代码
}catch(异常类型1 变量){
//异常处理
}
②分类:
运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如:数组索引越界异常)
编译时异常:编译阶段就会出现错误提醒的。(如:日期解析异常)
常见异常
ArrayIndexOutOfBoundsException 数组索引越界异常
NullPointerException 空指针异常
ClassCastException 类型转换异常
NumberFormatException 数字转换异常
③自定义异常
自定义编译时异常顺序
1、继承 Exception
2、重写构造器
public class AgeIIIegalExcpetion extends Exception{
public AgeIIIegalExcpetion() {
}
public AgeIIIegalExcpetion(String message) {
super(message);
}
}
自定义异常一:运行时异常
public class ExceptionDemo3 {
public static void main(String[] args) {
System.out.println("开始");
try {
save(0);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("结束");
}
public static void save(int age) {
if (age <= 0 || age > 150) {
throw new AgeIIIegalRuntimeExcpetion("age is xiaogao");
}
System.out.println("年龄保存成功了,年龄是:" + age);
}
}
public class AgeIIIegalExcpetion extends Exception{
public AgeIIIegalExcpetion() {
}
public AgeIIIegalExcpetion(String message) {
super(message);
}
}
//自定义异常:编译时异常(开发中不常用)
public class ExceptionDemo4 {
public static void main(String[] args) {
System.out.println("开始");
try {
save(0);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("结束");
}
public static void save(int age) throws AgeIIIegalExcpetion {
//throw 方法内部使用的,创建异常并从此跑出去
//throws 方法上,抛出方法内部的异常给调用者
if (age <= 0 || age > 150) {
throw new AgeIIIegalExcpetion("age is xiaogao");
}
System.out.println("年龄保存成功了,年龄是:" + age);
}
}
如果出现多个异常,就用他们的父类Exception捕获
//1、捕获异常,记录异常并响应合适的信息给用户
public class ExceptionDemo5 {
public static void main(String[] args) {
System.out.println("开始");
try {
parseDate("2023-11-11 11:11:11");
} catch (Exception e) { //直接用Exception捕获,要不然如果异常多,单个捕获,需要好多行
e.printStackTrace();
}
System.out.println("结束");
}
public static void parseDate(String s) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
System.out.println(d);
InputStream is = new FileInputStream("D:/meinv.png");
}
}
/*异常处理的标准*/
//2、捕获异常,尝试修复
public class ExceptionDemo6 {
public static void main(String[] args) {
while (true) {
try {
double price = getPrice();
System.out.println("本商品的定价是:" + price);
break;
} catch (Exception e) {
System.out.println("您输入的商品价格有误");
}
}
}
public static double getPrice(){
Scanner sc = new Scanner(System.in);
System.out.println("请您输入一个价格:");
double price = sc.nextDouble();
return price;
}
}
4.集合
集合体系:
Collection:单列集合,每个元素只包含一个值
集合特点:
List系列集合:添加元素是有序的、可重复、有索引。eg:ArrayList、LinekdList
Map:双列集合,每个元素包含两个值(键值对)。
集合特点:
Set系列集合:添加元素是无序的、不可重复、无索引。eg:HashSet
LinkedHashSet:有序、不重复、无索引
TreeSet:按照大小默认升序排列、不重复、无索引
public static void main(String[] args) {
//Collection提供的常用方法:是全部单列集合都可以直接用的。
Collection<String> list = new ArrayList<>();
// 1、添加数据 boolean add(E e)
list.add("java1");
list.add("java1");
list.add("赵敏");
list.add("赵敏");
list.add("小昭");
list.add("灭绝师太");
System.out.println(list);
// 2、清空集合
//list.clear();
//System.out.println(list);
// 3、判断集合是否为空
System.out.println(list.isEmpty());
// 4、直接删除集合中的某个数据:默认只能删除第一个java1
System.out.println(list.remove("java1"));
System.out.println(list);
// 5、判断集合中是否包含某个数据
System.out.println(list.contains("灭绝师太")); //true
System.out.println(list.contains("师太")); //false
// 6、获取集合的大小(元素个数)
System.out.println(list.size());
// 7、把集合转化成数组。
Object[] array = list.toArray();
System.out.println(Arrays.toString(array));
// 拓展:把别人集合的数据加给自己
String[] arrays = list.toArray(String[]::new);
System.out.println(Arrays.toString(arrays));
// 8、拓展一下:把别人集合的数据加给自己
Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
Collection<String> c2 = new ArrayList<>();
c2.add("java2");
c2.add("java3");
// 把c2集合的数据全部倒入给c1集合
c1.addAll(c2);
System.out.println(c1);
System.out.println(c2);
}
Collection集合的遍历
有三种遍历方式
//Collection集合的遍历方式一:迭代器Iterator遍历
public static void main(String[] args) {
//1、创建一个数组
ArrayList<String> list = new ArrayList<>();
list.add("赵敏");
list.add("古力娜扎");
list.add("玛尔扎哈");
System.out.println(list);
//2、得到这个集合对象的迭代器对象
Iterator<String> it = list.iterator();
//3、使用循环改进
while(it.hasNext()){ //当前位置有没有元素,有返回true
String ele = it.next(); //赋值后移到下一个位置
System.out.println(ele);
}
}
//Collection集合的遍历方式二:增强for遍历
public static void main(String[] args) {
//1、创建一个数组
ArrayList<String> list = new ArrayList<>();
list.add("赵敏");
list.add("古力娜扎");
list.add("玛尔扎哈");
System.out.println(list);
//2、增强for循环遍历集合
for (String s : list) { //不能改集合的数组,只能接收数据
System.out.println(s);
}
//3、增强for也可以遍历数组
int[] ages ={19,85,66,22};
for (int age: ages){ //类型 变量名:要遍历的数组名
System.out.println(age);
}
}
//Collection集合的遍历方式三:lambda遍历
public static void main(String[] args) {
//1、创建一个数组
ArrayList<String> list = new ArrayList<>();
list.add("赵敏");
list.add("古力娜扎");
list.add("玛尔扎哈");
System.out.println(list);
//2、遍历
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//简化
list.forEach(s ->System.out.println(s));
list.forEach(System.out::println);
}
注意事项:
三种遍历可能出现的并发修改异常问题。
注意:如果是Arraylist带索引的集合,我们也可以使用for循环删除每次退一步,或者从后面倒着遍历并删除!
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Java入门");
list.add("宁夏枸杞");
list.add("黑枸杞");
list.add("人字拖");
list.add("特技枸杞");
list.add("枸杞子");
//1、使用迭代器遍历集合并删除枸杞
//注意:如果使用迭代器遍历,并用集合删除数据,会出现并发修改异常ConcurrentModificationException,程序出bug
//所以必须调用迭代器自己的删除方法,才不会出现bug
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
if (name.contains("枸杞")) {
//list.remove(name); //不能用这个
iterator.remove();
}
}
System.out.println(list);
//2、使用增强for遍历集合并删除枸杞:(本质是迭代器遍历),但他只能接数据,不能操作,一定报错,无法解决
ArrayList<String> list2 = new ArrayList<>();
//3、使用Lambda遍历集合并删除枸杞:一定出错,而且无法解决(本质是增强for)
ArrayList<String> list3 = new ArrayList<>();
}
①LinkedList
//因为LinkedList对于首尾的操作很快,所以应用很广
//队列:先进先出,后进后出
public static void main(String[] args) {
//掌握LinkedList的应用
//1、做队列
LinkedList<String> queue = new LinkedList<>();
//2、入队
queue.addLast("第1个人"); //排队肯定是排到最后
queue.addLast("第2个人");
queue.addLast("第3个人");
queue.addLast("第4个人");
System.out.println(queue);
//3、出队
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue);
}
public static void main(String[] args) {
//1、做栈
LinkedList<String> stack = new LinkedList<>();
//2、入栈
stack.addFirst("第1颗子弹");
stack.addFirst("第2颗子弹");
stack.addFirst("第3颗子弹");
stack.addFirst("第4颗子弹");
stack.addFirst("第5颗子弹");//后进先出,先进后出
//stack.push(); 和queue.addFirst();一模一样
System.out.println(stack);
//3、出栈
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
System.out.println(stack.removeFirst());
//stack.pop();和stack.removeFirst()一样
System.out.println(stack);
}
②LinkedList常用方法
public static void main(String[] args) {
//1、一行经典代码,以后就常常这样写
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("小昭");
list.add("殷素素");
System.out.println(list);
//2、给某个位置插入一个数据
list.add(1,"赵敏");
//3、根据索引删除数据
System.out.println(list.remove(0));
System.out.println(list);
//4、修改索引位置处的数据
list.set(1,"灭绝师太");
System.out.println(list);
//5、根据索引取数据
System.out.println(list.get(3));
System.out.println("-----------");
//6、for循环
for (int i = 0; i < list.size(); i++) {
String ele = list.get(i);
System.out.println(ele);
}
System.out.println("-----------");
//7、迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
System.out.println("-----------");
//8、增强for循环
for(String s:list){
System.out.println(s);
}
System.out.println("-----------");
//9、Lambda
list.forEach( s-> System.out.println(s));
}
③Set集合
public static void main(String[] args) {
Set<Student> s = new HashSet<>(); //无序
Student s1 = new Student("石宇奇",'男',"羽毛球");
Student s2 = new Student("林丹",'男',"羽毛球");
Student s3 = new Student("陈康乐",'女',"羽毛球");
Student s4 = new Student("李梓嘉",'男',"羽毛球");
Student s5 = new Student("李梓嘉",'男',"羽毛球");
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
//System.out.println(s); //没去重,是因为s4和s5的哈希值不一致
//去重操作,在Student类中重写equals方法和hascode方法
System.out.println(s);
}
public static void main(String[] args) {
Set<Girl> set = new TreeSet<>();
set.add(new Girl("赵敏", '女', 21, 169.5)); //对象排序要自定义排序规则
set.add(new Girl("刘亦菲", '女', 34, 167.5));
set.add(new Girl("李若彤", '女', 21, 168.5));
set.add(new Girl("章若楠", '女', 26, 169.5));
//System.out.println(set); 报错
System.out.println(set); //return o.age - this.age 默认相等的会去掉,
System.out.println("--------------------------");
//方法二:TreeSet自带比较器对象Comparator,它可以定义的时候就写上
Set<Girl> set2 = new TreeSet<>((o1, o2) -> Double.compare(o1.getHeight(),o2.getHeight()));
set2.add(new Girl("赵敏", '女', 21, 169.5));
set2.add(new Girl("刘亦菲", '女', 34, 167.5));
set2.add(new Girl("李若彤", '女', 21, 168.5));
set2.add(new Girl("章若楠", '女', 26, 169.5));
System.out.println(set2);
}
④Collections
操作集合的工具类
public class Student implements Comparable<Student> {
private String name;
private int age;
private double height;
get、set、有参、无参、toString()
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
public static void main(String[] args) {
List<String> names = new ArrayList<>();
// 1、public static <T> boolean addAll(Collection<? super T> c, T...elements):为集合批量添加数据
Collections.addAll(names,"张无忌","小昭","赵敏","殷素素");
System.out.println(names);
// 2、public static void shuffle(List<?> list):打乱List集合中的元素顺序
Collections.shuffle(names);
System.out.println(names);
// 3、 public static <T> void sort(List<T> list):对List集合中的元素进行升序排序。
List<Student> students = new ArrayList<>();
Student s1 = new Student("赵敏", 19, 169.5);
Student s2 = new Student("周芷若", 18, 171.5);
Student s3 = new Student("周芷若", 18, 171.5);
Student s4 = new Student("小昭", 17, 165.5);
Collections.addAll(students, s1, s2, s3, s4);
// 方式一:让对象的类实现Comparable接口,从写compare方法,指定大小比较规则
Collections.sort(students);
System.out.println(students);
// 4、public static <T> void sort(List<T> list, Comparator<? super T> c):
// 对List集合中元素,按照比较器对象指定的规则进行排序
// 方式二:指定Comparator比较器对象,再指定比较规则。
Collections.sort(students,(o1, o2) -> Double.compare(o2.getHeight(), o1.getHeight()));
System.out.println(students);
}
⑤Lombok的用法
// Lombok : 使用注解简化get set 有参 无参构造器的写法。
// IDEA >= 2022
// Lombok 是 30版本 不要用28
@Data //包含无参 + get + set + toString + hashCode + equals
@NoArgsConstructor //无参(此处写无参就是因为,下面写了有参,那么Data拥有的有参就失效了)
@AllArgsConstructor //有参
public class Card {
private String number;
private String color;
private int size;
@Override
public String toString() {
return number + color;
}
}
⑥Map集合
Map体系整体特点:无序、键不可重复,无索引(键和值都可以是null)
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("Java入门到跑路",2);
map.put("华为手表",31);
map.put("IPhone16",2);
map.put("mate60pro",10);
map.put("IPhone16",21); //后面重复的键会覆盖前面整个数据
map.put("娃娃",1);
map.put(null,null );
System.out.println(map);
}
常用API
Map<String, Integer> map = new HashMap<>();
map.put("手表" ,2);
map.put("iphone" ,31);
map.put("huawei" ,365);
map.put("iphone" ,1);
map.put("娃娃", 31);
map.put("Java入门",1);
map.put(null,null);
System.out.println(map);
// map = {null=null, 手表=2, huawei=365, Java入门=1, 娃娃=31, iphone=1}
// 1、获取集合的大小(元素个数)
System.out.println(map.size()); // 6
// 2、清空集合
// map.clear();
// 3、判断集合是否为空
System.out.println(map.isEmpty());
// 4、根据键获取对应的值(重点)
System.out.println(map.get("手表"));
System.out.println(map.get("手表2")); //没有这个值就返回null
// 5、根据键删除整个数据,返回删除数据对应的值。(重点)
System.out.println(map.remove("娃娃"));
// 6、判断是否包含某个键(重点)'
// map = {null=null, 手表=2, huawei=365, Java入门=1,iphone=1}
System.out.println(map.containsKey("手表"));
System.out.println(map.containsKey("娃娃"));
// 7、判断是否包含某个值
// map = {null=null, 手表=2, huawei=365, Java入门=1,iphone=1}
System.out.println(map.containsValue(2));
System.out.println(map.containsValue(365));
// 8、获取Map集合的全部键,到一个Set集合中返回的
// map = {null=null, 手表=2, huawei=365, Java入门=1,iphone=1}
// public Set<K> keySet():
Set<String> keys = map.keySet();
System.out.println(keys);
// 9、获取Map集合的全部值:到一个Collection集合中返回的。
Collection<Integer> values = map.values();
System.out.println(values);
for (Integer value : values) {
System.out.println(value);
}
}
Map集合的遍历
Map集合遍历方式一:键找值
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("iphone",6);
map.put("小米",3);
map.put("huawei",3);
map.put("诺基亚",31);
System.out.println(map);
//1、获取map集合的全部键
Set<String> keys = map.keySet();
for (String key : keys) {
Integer value = map.get(key);
System.out.println(key+" ===> "+value);
}
}
Map集合遍历方式二:键值对
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("蜘蛛精",6);
map.put("紫霞",3);
map.put("至尊宝",3);
map.put("诺基亚",31);
System.out.println(map);
//想用增强for遍历,但是里面的数据类型无法确定
//所以就利用entrySet方法转换成Set集合来遍历(将数据类型封装成Map.Entry类型)
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println("键是:"+key+" 值是:"+value);
}
}
Map集合遍历方式三:Lambda
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("蜘蛛精", 1000);
map.put("小龙女", 23);
map.put("木婉清", 31);
map.put("黄蓉", 35);
System.out.println(map);
/*map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String k, Integer v) {
System.out.println(k + " " + v);
}
});*/
//简化
map.forEach((k, v) -> System.out.println(k + " " + v));
}
⑦TreeMap集合
按照键升序排序,不重复,无索引。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Movie {
private String name;
private double score;
private String actor;
}
// 方式二:TreeMap集合肯定可以自带比较器对象指定比较规则
Map<Movie, String> map = new TreeMap<>((m1, m2) -> Double.compare(m2.getScore(),m1.getScore()));
// 方式一:Movie类实现Comparable接口指定比较规则
map.put(new Movie("摔跤吧,爸爸", 9.5, "阿米尔汗"), "19:00");
map.put(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"), "20:50");
map.put(new Movie("三傻宝莱坞", 8.5, "阿米尔汗2"), "21:50");
map.put(new Movie("阿甘正传", 7.5, "汤姆汉克斯"), "21:00");
System.out.println(map);
⑧HashMap集合
按照键,无序,不重复,无索引。值不做要求,键和值都可以是null
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>();
map.put("手表" ,2);
map.put("iphone" ,31);
map.put("huawei" ,365);
map.put("iphone" ,1);
map.put("娃娃", 31);
map.put("Java入门",1);
map.put(null,null);
System.out.println(map);
}
⑨集合的嵌套
//例如:一个省份下面有好多个市。eg:江苏省:有南京市,常州市……
public static void main(String[] args) {
// 1、定义一个Map集合存储全部省份和城市信息。
//集合里面套集合
Map<String, List<String>> provinces = new HashMap<>();
// 2、存入省份信息
List<String> city1 = new ArrayList<>();
Collections.addAll(city1,"南京市","苏州市","无锡市","常州市");
provinces.put("江苏省",city1);
List<String> city2 = new ArrayList<>();
Collections.addAll(city2,"合肥市","芜湖市","滁州市","马鞍山市");
provinces.put("安徽省",city2);
List<String> city3 = new ArrayList<>();
Collections.addAll(city3,"保定市","石家庄市","唐山市","邢台市");
provinces.put("河北省",city3);
System.out.println(provinces);
List<String> anhui = provinces.get("安徽省");
for (String s : anhui) {
System.out.println(s);
}
}