五、JavaSE加强

目录

1.常用API

2.常用API(二)

3.异常

4.集合


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);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值